From cc4af37204824f7ca283833afa8400d4c98411b1 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Mon, 26 Oct 2020 14:03:49 +0200 Subject: [PATCH 001/106] graph iteration 2 strings --- OsmAnd/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index a30f9c4fc5..be2d6126ed 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,7 @@ Thx - Hardy --> + You must add at least two points. Wait for the route recalculation.\nGraph will be available after recalculation. %1$s data available only on the roads, you need to calculate a route using “Route between points” to get it. Graph From b5f06cf3c153d23ed977b4f45723c1aef921dea2 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Thu, 29 Oct 2020 18:09:09 +0200 Subject: [PATCH 002/106] Export voice --- .../main/java/net/osmand/IndexConstants.java | 2 + .../plus/activities/LocalIndexHelper.java | 2 +- .../settings/backend/ExportSettingsType.java | 4 +- .../backend/backup/FileSettingsItem.java | 26 ++++++- .../backend/backup/SettingsExporter.java | 39 +++++++++-- .../backend/backup/SettingsHelper.java | 70 ++++++++++++++++--- .../settings/backend/backup/SettingsItem.java | 2 +- .../ExportImportSettingsAdapter.java | 19 ++++- 8 files changed, 143 insertions(+), 21 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/IndexConstants.java b/OsmAnd-java/src/main/java/net/osmand/IndexConstants.java index c8ffd2d96b..31ac655f06 100644 --- a/OsmAnd-java/src/main/java/net/osmand/IndexConstants.java +++ b/OsmAnd-java/src/main/java/net/osmand/IndexConstants.java @@ -77,4 +77,6 @@ public class IndexConstants { public static final String TEMP_DIR = "temp/"; public static final String ROUTING_PROFILES_DIR = "routing/"; public static final String PLUGINS_DIR = "plugins/"; + + public static final String TTS_DIR_SUFFIX = "-tts"; } diff --git a/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java b/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java index 7c64e3a669..1e53f97603 100644 --- a/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java +++ b/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java @@ -214,7 +214,7 @@ public class LocalIndexHelper { return result; } - private void loadVoiceData(File voiceDir, List result, boolean backup, AbstractLoadLocalIndexTask loadTask) { + public void loadVoiceData(File voiceDir, List result, boolean backup, AbstractLoadLocalIndexTask loadTask) { if (voiceDir.canRead()) { //First list TTS files, they are preferred for (File voiceF : listFilesSorted(voiceDir)) { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java b/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java index 17901458ec..4c0ebc2c11 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java @@ -13,5 +13,7 @@ public enum ExportSettingsType { GLOBAL, OSM_NOTES, OSM_EDITS, - OFFLINE_MAPS + OFFLINE_MAPS, + TTS_VOICE, + VOICE } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index 097e64b0d2..151aaf61f6 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -33,6 +33,7 @@ public class FileSettingsItem extends StreamSettingsItem { OBF_MAP("obf_map", IndexConstants.MAPS_PATH), TILES_MAP("tiles_map", IndexConstants.TILES_INDEX_DIR), GPX("gpx", IndexConstants.GPX_INDEX_DIR), + TTS_VOICE("tts_voice", IndexConstants.VOICE_INDEX_DIR), VOICE("voice", IndexConstants.VOICE_INDEX_DIR), TRAVEL("travel", IndexConstants.WIKIVOYAGE_INDEX_DIR), MULTIMEDIA_NOTES("multimedia_notes", IndexConstants.AV_INDEX_DIR); @@ -66,6 +67,11 @@ public class FileSettingsItem extends StreamSettingsItem { return null; } + public static FileSubtype getSubtypeByPath(@NonNull OsmandApplication app, @NonNull String fileName) { + fileName = fileName.replace(app.getAppPath(null).getPath(), ""); + return getSubtypeByFileName(fileName); + } + public static FileSubtype getSubtypeByFileName(@NonNull String fileName) { String name = fileName; if (fileName.startsWith(File.separator)) { @@ -91,6 +97,11 @@ public class FileSettingsItem extends StreamSettingsItem { return subtype; } break; + case TTS_VOICE: + if (name.startsWith(subtype.subtypeFolder) && name.endsWith(IndexConstants.TTS_DIR_SUFFIX)) { + return subtype; + } + break; default: if (name.startsWith(subtype.subtypeFolder)) { return subtype; @@ -109,9 +120,10 @@ public class FileSettingsItem extends StreamSettingsItem { } protected File file; - private File appPath; + private final File appPath; protected FileSubtype subtype; private long size; + private boolean subFolders; public FileSettingsItem(@NonNull OsmandApplication app, @NonNull File file) throws IllegalArgumentException { super(app, file.getPath().replace(app.getAppPath(null).getPath(), "")); @@ -198,6 +210,14 @@ public class FileSettingsItem extends StreamSettingsItem { this.size = size; } + public boolean isSubFolders() { + return subFolders; + } + + public void setSubFolders(boolean subFolders) { + this.subFolders = subFolders; + } + @NonNull public File getFile() { return file; @@ -259,7 +279,9 @@ public class FileSettingsItem extends StreamSettingsItem { @Override public SettingsItemWriter getWriter() { try { - setInputStream(new FileInputStream(file)); + if (!file.isDirectory()) { + setInputStream(new FileInputStream(file)); + } } catch (FileNotFoundException e) { 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); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java index ccc23b5416..88809ea937 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java @@ -8,6 +8,7 @@ import org.json.JSONObject; import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -67,14 +68,44 @@ class SettingsExporter { if (Algorithms.isEmpty(fileName)) { fileName = item.getDefaultFileName(); } - ZipEntry entry = new ZipEntry(fileName); - zos.putNextEntry(entry); - writer.writeToStream(zos); - zos.closeEntry(); + if (item instanceof FileSettingsItem && ((FileSettingsItem) item).isSubFolders()) { + File file = ((FileSettingsItem) item).getFile(); + zipDirsWithFiles(file, writer, zos); + } else { + ZipEntry entry = new ZipEntry(fileName); + zos.putNextEntry(entry); + writer.writeToStream(zos); + zos.closeEntry(); + } } } } + public void zipDirsWithFiles(File f, SettingsItemWriter writer, ZipOutputStream zos) + throws IOException { + if (f == null) { + return; + } + if (f.isDirectory()) { + File[] fs = f.listFiles(); + if (fs != null) { + for (File c : fs) { + zipDirsWithFiles(c, writer, zos); + } + } + } else { + FileSettingsItem item = (FileSettingsItem) writer.getItem(); + String zipEntryName = Algorithms.isEmpty(item.getSubtype().getSubtypeFolder()) + ? f.getName() + : f.getPath().substring(f.getPath().indexOf(item.getSubtype().getSubtypeFolder())); + ZipEntry entry = new ZipEntry(zipEntryName); + zos.putNextEntry(entry); + item.setInputStream(new FileInputStream(f)); + writer.writeToStream(zos); + zos.closeEntry(); + } + } + private JSONObject createItemsJson() throws JSONException { JSONObject json = new JSONObject(); json.put("version", SettingsHelper.VERSION); 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 0cfa472ef0..0af0aa08b8 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -48,6 +48,7 @@ import java.util.Set; import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT; import static net.osmand.plus.activities.LocalIndexHelper.*; +import static net.osmand.plus.settings.backend.backup.FileSettingsItem.*; /* Usage: @@ -535,9 +536,41 @@ public class SettingsHelper { if (!files.isEmpty()) { dataList.put(ExportSettingsType.OFFLINE_MAPS, files); } + List localVoiceFileList = getVoiceIndexInfo(); + files = getFilesByType(localVoiceFileList, LocalIndexType.TTS_VOICE_DATA); + if (!files.isEmpty()) { + dataList.put(ExportSettingsType.TTS_VOICE, files); + } + files = getFilesByType(localVoiceFileList, LocalIndexType.VOICE_DATA); + if (!files.isEmpty()) { + dataList.put(ExportSettingsType.VOICE, files); + } return dataList; } + private List getVoiceIndexInfo() { + LocalIndexHelper helper = new LocalIndexHelper(app); + List localVoiceInfoList = new ArrayList<>(); + helper.loadVoiceData(app.getAppPath(IndexConstants.VOICE_INDEX_DIR), localVoiceInfoList, false, + new AbstractLoadLocalIndexTask() { + @Override + public void loadFile(LocalIndexInfo... loaded) { + } + }); + return localVoiceInfoList; + } + + private List getFilesByType(List localVoiceFileList, LocalIndexType localIndexType) { + List files = new ArrayList<>(); + for (LocalIndexInfo map : localVoiceFileList) { + File file = new File(map.getPathToData()); + if (file.exists() && map.getType() == localIndexType) { + files.add(file); + } + } + return files; + } + private List getLocalMapFiles() { List files = new ArrayList<>(); LocalIndexHelper helper = new LocalIndexHelper(app); @@ -548,7 +581,8 @@ public class SettingsHelper { }); for (LocalIndexInfo map : localMapFileList) { File file = new File(map.getPathToData()); - if (file != null && file.exists() && map.getType() != LocalIndexType.TTS_VOICE_DATA) { + if (file.exists() && map.getType() != LocalIndexType.TTS_VOICE_DATA + && map.getType() != LocalIndexType.VOICE_DATA) { files.add(file); } } @@ -574,7 +608,11 @@ public class SettingsHelper { tileSourceTemplates.add((ITileSource) object); } else if (object instanceof File) { try { - settingsItems.add(new FileSettingsItem(app, (File) object)); + FileSettingsItem fileItem = new FileSettingsItem(app, (File) object); + settingsItems.add(fileItem); + if (FileSubtype.getSubtypeByPath(app, ((File) object).getPath()) == FileSubtype.VOICE) { + fileItem.setSubFolders(true); + } } catch (IllegalArgumentException e) { LOG.warn("Trying to export unsuported file type", e); } @@ -627,6 +665,8 @@ public class SettingsHelper { List renderFilesList = new ArrayList<>(); List multimediaFilesList = new ArrayList<>(); List tracksFilesList = new ArrayList<>(); + List ttsVoiceFilesList = new ArrayList<>(); + List voiceFilesList = new ArrayList<>(); List mapFilesList = new ArrayList<>(); List avoidRoads = new ArrayList<>(); List globalSettingsItems = new ArrayList<>(); @@ -639,19 +679,23 @@ public class SettingsHelper { break; case FILE: FileSettingsItem fileItem = (FileSettingsItem) item; - if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.RENDERING_STYLE) { + if (fileItem.getSubtype() == FileSubtype.RENDERING_STYLE) { renderFilesList.add(fileItem.getFile()); - } else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.ROUTING_CONFIG) { + } else if (fileItem.getSubtype() == FileSubtype.ROUTING_CONFIG) { routingFilesList.add(fileItem.getFile()); - } else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.MULTIMEDIA_NOTES) { + } else if (fileItem.getSubtype() == FileSubtype.MULTIMEDIA_NOTES) { multimediaFilesList.add(fileItem.getFile()); - } else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.GPX) { + } else if (fileItem.getSubtype() == FileSubtype.GPX) { tracksFilesList.add(fileItem.getFile()); - } else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.OBF_MAP - || fileItem.getSubtype() == FileSettingsItem.FileSubtype.WIKI_MAP - || fileItem.getSubtype() == FileSettingsItem.FileSubtype.SRTM_MAP - || fileItem.getSubtype() == FileSettingsItem.FileSubtype.TILES_MAP) { + } else if (fileItem.getSubtype() == FileSubtype.OBF_MAP + || fileItem.getSubtype() == FileSubtype.WIKI_MAP + || fileItem.getSubtype() == FileSubtype.SRTM_MAP + || fileItem.getSubtype() == FileSubtype.TILES_MAP) { mapFilesList.add(fileItem); + } else if (fileItem.getSubtype() == FileSubtype.TTS_VOICE) { + ttsVoiceFilesList.add(fileItem.getFile()); + } else if (fileItem.getSubtype() == FileSubtype.VOICE) { + voiceFilesList.add(fileItem.getFile()); } break; case QUICK_ACTIONS: @@ -749,6 +793,12 @@ public class SettingsHelper { if (!mapFilesList.isEmpty()) { settingsToOperate.put(ExportSettingsType.OFFLINE_MAPS, mapFilesList); } + if (!ttsVoiceFilesList.isEmpty()) { + settingsToOperate.put(ExportSettingsType.TTS_VOICE, ttsVoiceFilesList); + } + if (!voiceFilesList.isEmpty()) { + settingsToOperate.put(ExportSettingsType.VOICE, voiceFilesList); + } return settingsToOperate; } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java index caf2d57301..e54cc99409 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java @@ -88,7 +88,7 @@ public abstract class SettingsItem { public boolean applyFileName(@NonNull String fileName) { String n = getFileName(); - return n != null && n.endsWith(fileName); + return n != null && (n.endsWith(fileName) || fileName.startsWith(n)); } public boolean shouldReadOnCollecting() { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java index 0f86486851..e865b9a21b 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java @@ -287,8 +287,7 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { title.setText(FileNameTranslationHelper.getFileName(app, app.getResourceManager().getOsmandRegions(), file.getName())); - FileSubtype subtype = FileSubtype.getSubtypeByFileName(file.getPath().replace( - app.getAppPath(null).getPath(), "")); + FileSubtype subtype = FileSubtype.getSubtypeByPath(app, file.getPath()); switch (subtype) { case SRTM_MAP: iconId = R.drawable.ic_plugin_srtm; @@ -303,6 +302,18 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { subText.setText(AndroidUtils.formatSize(app, size)); subText.setVisibility(View.VISIBLE); break; + case TTS_VOICE: + file = (File) currentItem; + title.setText(FileNameTranslationHelper.getFileName(app, + app.getResourceManager().getOsmandRegions(), + file.getName())); + setupIcon(icon, R.drawable.ic_action_volume_up, itemSelected); + case VOICE: + file = (File) currentItem; + title.setText(FileNameTranslationHelper.getFileName(app, + app.getResourceManager().getOsmandRegions(), + file.getName())); + setupIcon(icon, R.drawable.ic_action_volume_up, itemSelected); default: return child; } @@ -393,6 +404,10 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { return R.string.osm_edit_modified_poi; case OFFLINE_MAPS: return R.string.shared_string_local_maps; + case TTS_VOICE: + return R.string.local_indexes_cat_tts; + case VOICE: + return R.string.local_indexes_cat_voice; default: return R.string.access_empty_list; } From e4fe6564e6f057d330527f3588a02fb4fa373faf Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Fri, 30 Oct 2020 19:41:12 +0200 Subject: [PATCH 003/106] Fix bugs, complete graphs logic, remove copy-paste, refactoring --- .../fragment_measurement_tool_graph.xml | 65 ++- OsmAnd/res/values/attrs.xml | 1 + OsmAnd/res/values/styles.xml | 2 + .../plus/helpers/CustomBarChartRenderer.java | 30 ++ .../net/osmand/plus/helpers/GpxUiHelper.java | 67 ++++ .../plus/measurementtool/GraphsCard.java | 371 +++++++++--------- .../MeasurementEditingContext.java | 4 + .../MeasurementToolFragment.java | 62 ++- .../graph/BaseGraphAdapter.java | 82 ++++ .../graph/CommonGraphAdapter.java | 152 +++++++ .../graph/CustomGraphAdapter.java | 187 +++++++++ .../graph/GraphAdapterHelper.java | 145 +++++++ .../plus/myplaces/TrackSegmentFragment.java | 69 +--- .../RouteDetailsFragment.java | 172 ++------ .../routepreparationmenu/cards/BaseCard.java | 9 - .../cards/RouteInfoCard.java | 142 ++----- .../cards/RouteStatisticCard.java | 131 +------ 17 files changed, 1036 insertions(+), 655 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/helpers/CustomBarChartRenderer.java create mode 100644 OsmAnd/src/net/osmand/plus/measurementtool/graph/BaseGraphAdapter.java create mode 100644 OsmAnd/src/net/osmand/plus/measurementtool/graph/CommonGraphAdapter.java create mode 100644 OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java create mode 100644 OsmAnd/src/net/osmand/plus/measurementtool/graph/GraphAdapterHelper.java diff --git a/OsmAnd/res/layout/fragment_measurement_tool_graph.xml b/OsmAnd/res/layout/fragment_measurement_tool_graph.xml index 3d14187712..45f0b484d5 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool_graph.xml +++ b/OsmAnd/res/layout/fragment_measurement_tool_graph.xml @@ -51,8 +51,13 @@ android:layout_width="match_parent" android:layout_height="@dimen/route_info_chart_height" /> - + + - + android:orientation="vertical"> + + + + + + + + + + + + diff --git a/OsmAnd/res/values/attrs.xml b/OsmAnd/res/values/attrs.xml index 5ffd847b3a..8e8c8aee32 100644 --- a/OsmAnd/res/values/attrs.xml +++ b/OsmAnd/res/values/attrs.xml @@ -19,6 +19,7 @@ + diff --git a/OsmAnd/res/values/styles.xml b/OsmAnd/res/values/styles.xml index ea305b19d2..d96c5fa196 100644 --- a/OsmAnd/res/values/styles.xml +++ b/OsmAnd/res/values/styles.xml @@ -92,6 +92,7 @@ @style/Widget.Styled.ActionBarLight @color/list_background_color_light @drawable/circle_background_light + @drawable/circle_contour_bg_light @drawable/btn_round_light @drawable/btn_round_border_light @drawable/btn_round_border_light_2 @@ -394,6 +395,7 @@ @style/Widget.Styled.ActionBarDark @color/list_background_color_dark @drawable/circle_background_dark + @drawable/circle_contour_bg_dark @drawable/btn_round_dark @drawable/btn_round_border_dark @drawable/btn_round_border_dark_2 diff --git a/OsmAnd/src/net/osmand/plus/helpers/CustomBarChartRenderer.java b/OsmAnd/src/net/osmand/plus/helpers/CustomBarChartRenderer.java new file mode 100644 index 0000000000..3321399dbf --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/helpers/CustomBarChartRenderer.java @@ -0,0 +1,30 @@ +package net.osmand.plus.helpers; + +import android.graphics.RectF; + +import androidx.annotation.NonNull; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; + +import net.osmand.AndroidUtils; + +public class CustomBarChartRenderer extends HorizontalBarChartRenderer { + private float highlightHalfWidth; + + public CustomBarChartRenderer(@NonNull BarChart chart) { + this(chart, AndroidUtils.dpToPx(chart.getContext(), 1f) / 2f); + } + + public CustomBarChartRenderer(@NonNull BarChart chart, float highlightHalfWidth) { + super(chart, chart.getAnimator(), chart.getViewPortHandler()); + this.highlightHalfWidth = highlightHalfWidth; + } + + @Override + protected void setHighlightDrawPos(Highlight high, RectF bar) { + bar.left = high.getDrawX() - highlightHalfWidth; + bar.right = high.getDrawX() + highlightHalfWidth; + } +} diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index 47650dc2ec..c563be0769 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -75,6 +75,8 @@ import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuItem; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GpxDbHelper.GpxDataItemCallback; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmAndConstants; import net.osmand.plus.OsmAndFormatter; @@ -2045,6 +2047,71 @@ public class GpxUiHelper { return gpx; } + public enum LineGraphType { + ALTITUDE, + SLOPE, + SPEED; + } + + public static List getDataSets(LineChart chart, + OsmandApplication app, + GPXTrackAnalysis analysis, + boolean calcWithoutGaps, + LineGraphType... types) { + if (app == null || chart == null || analysis == null || types == null) { + return Collections.emptyList(); + } + List dataList = new ArrayList<>(); + for (LineGraphType type : types) { + switch (type) { + case ALTITUDE: { + if (analysis.hasElevationData) { + OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, false, true, calcWithoutGaps); + dataList.add(elevationDataSet); + } + break; + } + case SLOPE: + if (analysis.hasElevationData) { + OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, null, true, true, calcWithoutGaps); + dataList.add(slopeDataSet); + } + break; + case SPEED: { + if (analysis.hasSpeedData) { + OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, false, true, calcWithoutGaps); + dataList.add(speedDataSet); + } + break; + } + } + } + if (dataList.size() > 0) { + Collections.sort(dataList, new Comparator() { + @Override + public int compare(OrderedLineDataSet o1, OrderedLineDataSet o2) { + return Float.compare(o1.getPriority(), o2.getPriority()); + } + }); + } + return new ArrayList(dataList); + } + + public static GpxDisplayItem makeGpxDisplayItem(OsmandApplication app, GPXUtilities.GPXFile gpx) { + GpxDisplayItem gpxItem = null; + String groupName = app.getString(R.string.current_route); + GpxDisplayGroup group = app.getSelectedGpxHelper().buildGpxDisplayGroup(gpx, 0, groupName); + if (group != null && group.getModifiableList().size() > 0) { + gpxItem = group.getModifiableList().get(0); + if (gpxItem != null) { + gpxItem.route = true; + } + } + return gpxItem; + } public static class GPXInfo { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java index 9a5cbeffba..3ae28d83b2 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java @@ -1,10 +1,12 @@ package net.osmand.plus.measurementtool; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; +import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -16,17 +18,25 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.SettingsBaseActivity; import net.osmand.plus.helpers.GpxUiHelper; -import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; -import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; +import net.osmand.plus.helpers.GpxUiHelper.LineGraphType; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter; +import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener; +import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.measurementtool.MeasurementToolFragment.OnUpdateAdditionalInfoListener; +import net.osmand.plus.measurementtool.graph.CommonGraphAdapter; +import net.osmand.plus.measurementtool.graph.CustomGraphAdapter; +import net.osmand.plus.measurementtool.graph.CustomGraphAdapter.LegendViewType; +import net.osmand.plus.measurementtool.graph.BaseGraphAdapter; +import net.osmand.plus.measurementtool.graph.GraphAdapterHelper; import net.osmand.plus.routepreparationmenu.RouteDetailsFragment; import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.plus.routepreparationmenu.cards.RouteStatisticCard; import net.osmand.router.RouteSegmentResult; import net.osmand.util.Algorithms; @@ -36,44 +46,52 @@ import static net.osmand.GPXUtilities.GPXFile; import static net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; +import java.util.Arrays; import java.util.List; public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListener { private static String GRAPH_DATA_GPX_FILE_NAME = "graph_data_tmp"; + private static int INVALID_ID = -1; private MeasurementEditingContext editingCtx; private MeasurementToolFragment fragment; - private GraphType visibleGraphType; + private GraphType visibleType; private List graphTypes = new ArrayList<>(); + private GpxDisplayItem gpxItem; private View commonGraphContainer; private View customGraphContainer; private View messageContainer; - private LineChart commonGraphChart; - private HorizontalBarChart customGraphChart; + private CommonGraphAdapter commonGraphAdapter; + private CustomGraphAdapter customGraphAdapter; private RecyclerView graphTypesMenu; - private enum CommonGraphType { - OVERVIEW(R.string.shared_string_overview, false), - ALTITUDE(R.string.altitude, true), - SLOPE(R.string.shared_string_slope, true), - SPEED(R.string.map_widget_speed, false); + private TrackDetailsMenu trackDetailsMenu; - CommonGraphType(int titleId, boolean canBeCalculated) { + private enum CommonGraphType { + OVERVIEW(R.string.shared_string_overview, true, LineGraphType.ALTITUDE, LineGraphType.SLOPE), + ALTITUDE(R.string.altitude, true, LineGraphType.ALTITUDE), + SLOPE(R.string.shared_string_slope, true, LineGraphType.SLOPE), + SPEED(R.string.map_widget_speed, false, LineGraphType.SPEED); + + CommonGraphType(int titleId, boolean canBeCalculated, LineGraphType ... lineGraphTypes) { this.titleId = titleId; this.canBeCalculated = canBeCalculated; + this.lineGraphTypes = lineGraphTypes; } final int titleId; final boolean canBeCalculated; + final LineGraphType[] lineGraphTypes; } - public GraphsCard(@NonNull MapActivity mapActivity, MeasurementToolFragment fragment) { + public GraphsCard(@NonNull MapActivity mapActivity, + TrackDetailsMenu trackDetailsMenu, + MeasurementToolFragment fragment) { super(mapActivity); + this.trackDetailsMenu = trackDetailsMenu; this.fragment = fragment; } @@ -82,19 +100,27 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen if (mapActivity == null || fragment == null) return; editingCtx = fragment.getEditingCtx(); + graphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); + graphTypesMenu.setLayoutManager(new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); commonGraphContainer = view.findViewById(R.id.common_graphs_container); customGraphContainer = view.findViewById(R.id.custom_graphs_container); messageContainer = view.findViewById(R.id.message_container); - commonGraphChart = (LineChart) view.findViewById(R.id.line_chart); - customGraphChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); - updateGraphData(); + LineChart lineChart = (LineChart) view.findViewById(R.id.line_chart); + HorizontalBarChart barChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); + commonGraphAdapter = new CommonGraphAdapter(lineChart, true); + customGraphAdapter = new CustomGraphAdapter(barChart, true); - graphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); - graphTypesMenu.setLayoutManager( - new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); + customGraphAdapter.setLegendContainer((ViewGroup) view.findViewById(R.id.route_legend)); + customGraphAdapter.setLayoutChangeListener(new BaseGraphAdapter.LayoutChangeListener() { + @Override + public void onLayoutChanged() { + setLayoutNeeded(); + } + }); - refreshGraphTypesSelectionMenu(); - updateDataView(); + GraphAdapterHelper.bindGraphAdapters(commonGraphAdapter, Arrays.asList((BaseGraphAdapter) customGraphAdapter), (ViewGroup) view); + GraphAdapterHelper.bindToMap(commonGraphAdapter, mapActivity, trackDetailsMenu); + fullUpdate(); } @Override @@ -104,15 +130,29 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen @Override public void onUpdateAdditionalInfo() { - if (!isRouteCalculating()) { - updateGraphData(); - refreshGraphTypesSelectionMenu(); - } - updateDataView(); + fullUpdate(); } - private void refreshGraphTypesSelectionMenu() { - graphTypesMenu.removeAllViews(); + private void fullUpdate() { + if (!isRouteCalculating()) { + updateData(); + updateVisibleType(); + updateTypesMenu(); + } + updateInfoView(); + } + + private void updateTypesMenu() { + if (!editingCtx.isPointsEnoughToCalculateRoute()) { + graphTypesMenu.setVisibility(View.GONE); + } else { + graphTypesMenu.setVisibility(View.VISIBLE); + graphTypesMenu.removeAllViews(); + fillInTypesMenu(); + } + } + + private void fillInTypesMenu() { OsmandApplication app = getMyApplication(); int activeColorId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; final HorizontalSelectionAdapter adapter = new HorizontalSelectionAdapter(app, nightMode); @@ -127,16 +167,16 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen } } adapter.setItems(items); - String selectedItemKey = visibleGraphType.getTitle(); + String selectedItemKey = visibleType.getTitle(); adapter.setSelectedItemByTitle(selectedItemKey); - adapter.setListener(new HorizontalSelectionAdapter.HorizontalSelectionAdapterListener() { + adapter.setListener(new HorizontalSelectionAdapterListener() { @Override - public void onItemSelected(HorizontalSelectionAdapter.HorizontalSelectionItem item) { + public void onItemSelected(HorizontalSelectionItem item) { adapter.setItems(items); adapter.setSelectedItem(item); - GraphType chosenGraphType = (GraphType) item.getObject(); - if (!isCurrentVisibleType(chosenGraphType)) { - setupVisibleGraphType(chosenGraphType); + GraphType chosenType = (GraphType) item.getObject(); + if (!isCurrentVisibleType(chosenType)) { + changeVisibleType(chosenType); } } }); @@ -144,19 +184,19 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen adapter.notifyDataSetChanged(); } - private void setupVisibleGraphType(GraphType type) { - visibleGraphType = type; - updateDataView(); + private void changeVisibleType(GraphType type) { + visibleType = type; + updateInfoView(); } private boolean isCurrentVisibleType(GraphType type) { - if (visibleGraphType != null && type != null) { - return Algorithms.objectEquals(visibleGraphType.getTitle(), type.getTitle()); + if (visibleType != null && type != null) { + return Algorithms.objectEquals(visibleType.getTitle(), type.getTitle()); } return false; } - private GraphType getFirstAvailableGraphType() { + private GraphType getFirstAvailableType() { for (GraphType type : graphTypes) { if (type.isAvailable()) { return type; @@ -165,189 +205,146 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen return null; } - private void updateDataView() { - if (isRouteCalculating()) { - showProgressMessage(); - } else if (visibleGraphType.hasData()) { + private void updateInfoView() { + hideAll(); + if (!editingCtx.isPointsEnoughToCalculateRoute()) { + showMessage(app.getString(R.string.message_you_need_add_two_points_to_show_graphs)); + } else if (isRouteCalculating()) { + showMessage(app.getString(R.string.message_graph_will_be_available_after_recalculation), true); + } else if (visibleType.hasData()) { showGraph(); - } else if (visibleGraphType.canBeCalculated()) { - showMessage(); + } else if (visibleType.canBeCalculated()) { + showMessage(app.getString(R.string.message_need_calculate_route_before_show_graph, + visibleType.getTitle()), R.drawable.ic_action_altitude_average, + app.getString(R.string.route_between_points), new View.OnClickListener() { + @Override + public void onClick(View v) { + fragment.startSnapToRoad(false); + } + }); } } - private void showProgressMessage() { + private void hideAll() { commonGraphContainer.setVisibility(View.GONE); customGraphContainer.setVisibility(View.GONE); + messageContainer.setVisibility(View.GONE); + } + + private void showMessage(String text) { + showMessage(text, INVALID_ID, false, null, null); + } + + private void showMessage(String text, @DrawableRes int iconResId, String btnTitle, View.OnClickListener btnListener) { + showMessage(text, iconResId, false, btnTitle, btnListener); + } + + private void showMessage(String text, boolean showProgressBar) { + showMessage(text, INVALID_ID, showProgressBar, null, null); + } + + private void showMessage(@NonNull String text, + @DrawableRes int iconResId, + boolean showProgressBar, + String btnTitle, + View.OnClickListener btnListener) { messageContainer.setVisibility(View.VISIBLE); TextView tvMessage = messageContainer.findViewById(R.id.message_text); + tvMessage.setText(text); ImageView icon = messageContainer.findViewById(R.id.message_icon); + if (iconResId != INVALID_ID) { + icon.setVisibility(View.VISIBLE); + icon.setImageResource(iconResId); + } else { + icon.setVisibility(View.GONE); + } ProgressBar pb = messageContainer.findViewById(R.id.progress_bar); - pb.setVisibility(View.VISIBLE); - icon.setVisibility(View.GONE); - tvMessage.setText(R.string.message_graph_will_be_available_after_recalculation); + pb.setVisibility(showProgressBar ? View.VISIBLE : View.GONE); + View btnContainer = messageContainer.findViewById(R.id.btn_container); + if (btnTitle != null) { + TextView tvBtnTitle = btnContainer.findViewById(R.id.btn_text); + tvBtnTitle.setText(btnTitle); + btnContainer.setVisibility(View.VISIBLE); + } else { + btnContainer.setVisibility(View.GONE); + } + if (btnListener != null) { + btnContainer.setOnClickListener(btnListener); + } } private void showGraph() { - if (visibleGraphType.isCustom()) { - customGraphChart.clear(); - commonGraphContainer.setVisibility(View.GONE); + if (visibleType.isCustom()) { + CustomGraphType customGraphType = (CustomGraphType) visibleType; customGraphContainer.setVisibility(View.VISIBLE); - messageContainer.setVisibility(View.GONE); - prepareCustomGraphView((BarData) visibleGraphType.getGraphData()); + customGraphAdapter.setLegendViewType(LegendViewType.ONE_ELEMENT); + customGraphAdapter.fullUpdate((BarData) customGraphType.getGraphData(), customGraphType.getStatistics()); } else { - commonGraphChart.clear(); commonGraphContainer.setVisibility(View.VISIBLE); - customGraphContainer.setVisibility(View.GONE); - messageContainer.setVisibility(View.GONE); - prepareCommonGraphView((LineData) visibleGraphType.getGraphData()); + customGraphAdapter.setLegendViewType(LegendViewType.GONE); + commonGraphAdapter.fullUpdate((LineData) visibleType.getGraphData(), gpxItem); } } - private void showMessage() { - commonGraphContainer.setVisibility(View.GONE); - customGraphContainer.setVisibility(View.GONE); - messageContainer.setVisibility(View.VISIBLE); - TextView tvMessage = messageContainer.findViewById(R.id.message_text); - ImageView icon = messageContainer.findViewById(R.id.message_icon); - ProgressBar pb = messageContainer.findViewById(R.id.progress_bar); - pb.setVisibility(View.GONE); - icon.setVisibility(View.VISIBLE); - tvMessage.setText(app.getString( - R.string.message_need_calculate_route_before_show_graph, - visibleGraphType.getTitle())); - icon.setImageResource(R.drawable.ic_action_altitude_average); - } - - private void prepareCommonGraphView(LineData data) { - GpxUiHelper.setupGPXChart(commonGraphChart, 4, 24f, 16f, !nightMode, true); - commonGraphChart.setData(data); - } - - private void prepareCustomGraphView(BarData data) { - OsmandApplication app = getMyApplication(); - if (app == null) return; - - GpxUiHelper.setupHorizontalGPXChart(app, customGraphChart, 5, 9, 24, true, nightMode); - customGraphChart.setExtraRightOffset(16); - customGraphChart.setExtraLeftOffset(16); - customGraphChart.setData(data); - } - - private void updateGraphData() { + private void updateData() { graphTypes.clear(); OsmandApplication app = getMyApplication(); - GPXTrackAnalysis analysis = createGpxTrackAnalysis(); + GPXFile gpxFile = getGpxFile(); + GPXTrackAnalysis analysis = gpxFile != null ? gpxFile.getAnalysis(0) : null; + gpxItem = gpxFile != null ? GpxUiHelper.makeGpxDisplayItem(app, gpxFile) : null; + if (gpxItem != null) { + trackDetailsMenu.setGpxItem(gpxItem); + } // update common graph data for (CommonGraphType commonType : CommonGraphType.values()) { - List dataSets = getDataSets(commonType, commonGraphChart, analysis); - LineData data = null; - if (!Algorithms.isEmpty(dataSets)) { - data = new LineData(dataSets); - } + List dataSets = GpxUiHelper.getDataSets(commonGraphAdapter.getChart(), + app, analysis, false, commonType.lineGraphTypes); + LineData data = !Algorithms.isEmpty(dataSets) ? new LineData(dataSets) : null; String title = app.getString(commonType.titleId); - graphTypes.add(new GraphType(title, false, commonType.canBeCalculated, data)); + graphTypes.add(new GraphType(title, commonType.canBeCalculated, data)); } // update custom graph data - List routeSegments = editingCtx.getAllRouteSegments(); - List routeStatistics = calculateRouteStatistics(routeSegments); + List routeStatistics = calculateRouteStatistics(); if (analysis != null && routeStatistics != null) { for (RouteStatistics statistics : routeStatistics) { String title = SettingsBaseActivity.getStringRouteInfoPropertyValue(app, statistics.name); BarData data = null; if (!Algorithms.isEmpty(statistics.elements)) { - data = GpxUiHelper.buildStatisticChart( - app, customGraphChart, statistics, analysis, true, nightMode); + data = GpxUiHelper.buildStatisticChart(app, customGraphAdapter.getChart(), + statistics, analysis, true, nightMode); } - graphTypes.add(new GraphType(title, true, false, data)); + graphTypes.add(new CustomGraphType(title, false, data, statistics)); } } + } - // update current visible graph type - if (visibleGraphType == null) { - visibleGraphType = getFirstAvailableGraphType(); + private void updateVisibleType() { + if (visibleType == null) { + visibleType = getFirstAvailableType(); } else { for (GraphType type : graphTypes) { if (isCurrentVisibleType(type)) { - visibleGraphType = type.isAvailable() ? type : getFirstAvailableGraphType(); + visibleType = type.isAvailable() ? type : getFirstAvailableType(); break; } } } } - private List getDataSets(CommonGraphType type, LineChart chart, GPXTrackAnalysis analysis) { - List dataSets = new ArrayList<>(); - if (chart != null && analysis != null) { - OsmandApplication app = getMyApplication(); - switch (type) { - case OVERVIEW: { - List dataList = new ArrayList<>(); - if (analysis.hasSpeedData) { - OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, true, true, false); - dataList.add(speedDataSet); - } - if (analysis.hasElevationData) { - OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, false, true, false); - dataList.add(elevationDataSet); - OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, null, true, true, false); - dataList.add(slopeDataSet); - } - if (dataList.size() > 0) { - Collections.sort(dataList, new Comparator() { - @Override - public int compare(OrderedLineDataSet o1, OrderedLineDataSet o2) { - return Float.compare(o1.getPriority(), o2.getPriority()); - } - }); - } - dataSets.addAll(dataList); - break; - } - case ALTITUDE: { - if (analysis.hasElevationData) { - OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); - dataSets.add(elevationDataSet); - } - break; - } - case SLOPE: - if (analysis.hasElevationData) { - OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, null, true, true, false); - dataSets.add(slopeDataSet); - } - break; - case SPEED: { - if (analysis.hasSpeedData) { - OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); - dataSets.add(speedDataSet); - } - break; - } - } - } - return dataSets; - } - - private GPXTrackAnalysis createGpxTrackAnalysis() { - GPXFile gpx; - if (editingCtx.getGpxData() != null) { - gpx = editingCtx.getGpxData().getGpxFile(); + private GPXFile getGpxFile() { + if (fragment.isTrackReadyToCalculate()) { + return editingCtx.exportRouteAsGpx(GRAPH_DATA_GPX_FILE_NAME); } else { - gpx = editingCtx.exportRouteAsGpx(GRAPH_DATA_GPX_FILE_NAME); + GpxData gpxData = editingCtx.getGpxData(); + return gpxData != null ? gpxData.getGpxFile() : null; } - return gpx != null ? gpx.getAnalysis(0) : null; } - private List calculateRouteStatistics(List route) { + private List calculateRouteStatistics() { OsmandApplication app = getMyApplication(); + List route = editingCtx.getAllRouteSegments(); if (route == null || app == null) return null; return RouteDetailsFragment.calculateRouteStatistics(app, route, nightMode); } @@ -356,15 +353,13 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen return fragment.isProgressBarVisible(); } - private static class GraphType { + private class GraphType { private String title; - private boolean isCustom; private boolean canBeCalculated; private ChartData graphData; - public GraphType(String title, boolean isCustom, boolean canBeCalculated, ChartData graphData) { + public GraphType(String title, boolean canBeCalculated, ChartData graphData) { this.title = title; - this.isCustom = isCustom; this.canBeCalculated = canBeCalculated; this.graphData = graphData; } @@ -374,11 +369,15 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen } public boolean isCustom() { - return isCustom; + return this instanceof CustomGraphType; } public boolean isAvailable() { - return hasData() || canBeCalculated(); + return isPointsCountEnoughToCalculateRoute() && (hasData() || canBeCalculated()); + } + + private boolean isPointsCountEnoughToCalculateRoute() { + return editingCtx.getPointsCount() >= 2; } public boolean canBeCalculated() { @@ -393,4 +392,18 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen return graphData; } } + + private class CustomGraphType extends GraphType { + + private RouteStatistics statistics; + + public CustomGraphType(String title, boolean canBeCalculated, ChartData graphData, RouteStatistics statistics) { + super(title, canBeCalculated, graphData); + this.statistics = statistics; + } + + public RouteStatistics getStatistics() { + return statistics; + } + } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java index 307d89d501..ad6c5f4c4f 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java @@ -313,6 +313,10 @@ public class MeasurementEditingContext { return before.points.size(); } + public boolean isPointsEnoughToCalculateRoute() { + return getPointsCount() >= 2; + } + public List getAllRouteSegments() { List allSegments = new ArrayList<>(); for (Pair key : getOrderedRoadSegmentDataKeys()) { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index c40e7b70ca..9e6ecef9e3 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -52,6 +52,7 @@ import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.base.ContextMenuFragment.MenuState; import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.measurementtool.GpxApproximationFragment.GpxApproximationFragmentListener; import net.osmand.plus.measurementtool.GpxData.ActionType; import net.osmand.plus.measurementtool.OptionsBottomSheetDialogFragment.OptionsFragmentListener; @@ -116,8 +117,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private TextView distanceToCenterTv; private String pointsSt; private View additionalInfoContainer; - private ViewGroup additionalInfoCardsContainer; - private BaseCard visibleAdditionalInfoCard; + private ViewGroup cardsContainer; + private BaseCard visibleCard; + private PointsCard pointsCard; + private GraphsCard graphsCard; private LinearLayout customRadioButton; private View mainView; private ImageView upDownBtn; @@ -145,6 +148,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private int cachedMapPosition; private MeasurementEditingContext editingCtx = new MeasurementEditingContext(); + private GraphDetailsMenu detailsMenu; private LatLon initialPoint; @@ -164,6 +168,19 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route GRAPH } + private class GraphDetailsMenu extends TrackDetailsMenu { + + @Override + protected int getFragmentWidth() { + return mainView.getWidth(); + } + + @Override + protected int getFragmentHeight() { + return mainView.getHeight(); + } + } + private void setEditingCtx(MeasurementEditingContext editingCtx) { this.editingCtx = editingCtx; } @@ -257,8 +274,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route mainView = view.findViewById(R.id.main_view); AndroidUtils.setBackground(mapActivity, mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark); + detailsMenu = new GraphDetailsMenu(); additionalInfoContainer = mainView.findViewById(R.id.additional_info_container); - additionalInfoCardsContainer = mainView.findViewById(R.id.cards_container); + cardsContainer = mainView.findViewById(R.id.cards_container); if (portrait) { customRadioButton = mainView.findViewById(R.id.custom_radio_buttons); @@ -282,6 +300,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } }); } + pointsCard = new PointsCard(mapActivity, this); + graphsCard = new GraphsCard(mapActivity, detailsMenu, this); if (progressBarVisible) { showProgressBar(); @@ -517,29 +537,28 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (!additionalInfoExpanded || !isCurrentAdditionalInfoType(type)) { MapActivity ma = getMapActivity(); if (ma == null) return; - currentAdditionalInfoType = type; - updateUpDownBtn(); + OsmandApplication app = ma.getMyApplication(); - BaseCard additionalInfoCard = null; if (AdditionalInfoType.POINTS == type) { - additionalInfoCard = new PointsCard(ma, this); + visibleCard = pointsCard; UiUtilities.updateCustomRadioButtons(app, customRadioButton, nightMode, START); } else if (AdditionalInfoType.GRAPH == type) { - additionalInfoCard = new GraphsCard(ma, this); + visibleCard = graphsCard; UiUtilities.updateCustomRadioButtons(app, customRadioButton, nightMode, END); } - if (additionalInfoCard != null) { - visibleAdditionalInfoCard = additionalInfoCard; - additionalInfoCardsContainer.removeAllViews(); - additionalInfoCardsContainer.addView(additionalInfoCard.build(ma)); - additionalInfoExpanded = true; - } + cardsContainer.removeAllViews(); + View cardView = visibleCard.getView() != null ? visibleCard.getView() : visibleCard.build(ma); + cardsContainer.addView(cardView); + + currentAdditionalInfoType = type; + additionalInfoExpanded = true; + updateUpDownBtn(); } } private void updateAdditionalInfoView() { - if (visibleAdditionalInfoCard instanceof OnUpdateAdditionalInfoListener) { - ((OnUpdateAdditionalInfoListener) visibleAdditionalInfoCard).onUpdateAdditionalInfo(); + if (visibleCard instanceof OnUpdateAdditionalInfoListener) { + ((OnUpdateAdditionalInfoListener) visibleCard).onUpdateAdditionalInfo(); } } @@ -597,6 +616,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route super.onResume(); MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { + detailsMenu.setMapActivity(mapActivity); mapActivity.getMapLayers().getMapControlsLayer().addThemeInfoProviderTag(TAG); mapActivity.getMapLayers().getMapControlsLayer().showMapControlsIfHidden(); cachedMapPosition = mapActivity.getMapView().getMapPosition(); @@ -612,6 +632,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (mapActivity != null) { mapActivity.getMapLayers().getMapControlsLayer().removeThemeInfoProviderTag(TAG); } + detailsMenu.onDismiss(); + detailsMenu.setMapActivity(null); setMapPosition(cachedMapPosition); } @@ -687,7 +709,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - private void startSnapToRoad(boolean rememberPreviousTitle) { + public void startSnapToRoad(boolean rememberPreviousTitle) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { if (rememberPreviousTitle) { @@ -1219,7 +1241,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route final ApplicationMode appMode = editingCtx.getAppMode(); if (mapActivity != null) { Drawable icon; - if (editingCtx.isTrackSnappedToRoad() || editingCtx.isNewData() || approximationApplied) { + if (isTrackReadyToCalculate()) { if (appMode == MeasurementEditingContext.DEFAULT_APP_MODE) { icon = getActiveIcon(R.drawable.ic_action_split_interval); } else { @@ -1234,6 +1256,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } + public boolean isTrackReadyToCalculate() { + return editingCtx.isTrackSnappedToRoad() || editingCtx.isNewData() || approximationApplied; + } + private void hideSnapToRoadIcon() { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/BaseGraphAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/BaseGraphAdapter.java new file mode 100644 index 0000000000..dc83460a3f --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/BaseGraphAdapter.java @@ -0,0 +1,82 @@ +package net.osmand.plus.measurementtool.graph; + +import android.view.MotionEvent; + +import com.github.mikephil.charting.charts.Chart; +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.listener.ChartTouchListener; + +import net.osmand.plus.OsmandApplication; + +public abstract class BaseGraphAdapter { + + private Highlight lastKnownHighlight; + protected CHART mChart; + protected CHART_DATA mChartData; + protected DATA mAdditionalData; + protected boolean usedOnMap; + + public BaseGraphAdapter(CHART chart, boolean usedOnMap) { + this.mChart = chart; + this.usedOnMap = usedOnMap; + prepareCharterView(); + } + + protected void prepareCharterView() { + mChart.setExtraRightOffset(16); + mChart.setExtraLeftOffset(16); + } + + public CHART getChart() { + return mChart; + } + + protected void updateHighlight() { + highlight(lastKnownHighlight); + } + + public void highlight(Highlight h) { + this.lastKnownHighlight = h; + } + + public void fullUpdate(CHART_DATA chartData, DATA data) { + updateData(chartData, data); + updateView(); + } + + public void updateData(CHART_DATA chartData, DATA data) { + this.mChartData = chartData; + this.mAdditionalData = data; + } + + public abstract void updateView(); + + protected boolean isNightMode() { + OsmandApplication app = getMyApplication(); + if (app != null) { + return usedOnMap ? app.getDaynightHelper().isNightModeForMapControls() + : !app.getSettings().isLightContent(); + } + return false; + } + + protected OsmandApplication getMyApplication() { + return (OsmandApplication) mChart.getContext().getApplicationContext(); + } + + public interface ExternalValueSelectedListener { + void onValueSelected(Entry e, Highlight h); + void onNothingSelected(); + } + + public interface ExternalGestureListener { + void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture); + void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture, boolean hasTranslated); + } + + public interface LayoutChangeListener { + void onLayoutChanged(); + } +} diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/CommonGraphAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CommonGraphAdapter.java new file mode 100644 index 0000000000..693b5669e7 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CommonGraphAdapter.java @@ -0,0 +1,152 @@ +package net.osmand.plus.measurementtool.graph; + +import android.graphics.Matrix; +import android.view.MotionEvent; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.listener.ChartTouchListener; +import com.github.mikephil.charting.listener.OnChartGestureListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; + +import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; +import net.osmand.plus.helpers.GpxUiHelper; + +import java.util.HashMap; +import java.util.Map; + +public class CommonGraphAdapter extends BaseGraphAdapter { + + private Highlight highlight; + private Map externalValueSelectedListeners = new HashMap<>(); + private ExternalGestureListener externalGestureListener; + + public CommonGraphAdapter(LineChart chart, boolean usedOnMap) { + super(chart, usedOnMap); + } + + @Override + protected void prepareCharterView() { + super.prepareCharterView(); + + mChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() { + @Override + public void onValueSelected(Entry e, Highlight h) { + highlight = h; + for (ExternalValueSelectedListener listener : externalValueSelectedListeners.values()) { + listener.onValueSelected(e, h); + } + } + + @Override + public void onNothingSelected() { + for (ExternalValueSelectedListener listener : externalValueSelectedListeners.values()) { + listener.onNothingSelected(); + } + } + }); + + mChart.setOnChartGestureListener(new OnChartGestureListener() { + boolean hasTranslated = false; + float highlightDrawX = -1; + + @Override + public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + hasTranslated = false; + if (mChart.getHighlighted() != null && mChart.getHighlighted().length > 0) { + highlightDrawX = mChart.getHighlighted()[0].getDrawX(); + } else { + highlightDrawX = -1; + } + if (externalGestureListener != null) { + externalGestureListener.onChartGestureStart(me, lastPerformedGesture); + } + } + + @Override + public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + GpxDisplayItem gpxItem = getGpxItem(); + gpxItem.chartMatrix = new Matrix(mChart.getViewPortHandler().getMatrixTouch()); + Highlight[] highlights = mChart.getHighlighted(); + if (highlights != null && highlights.length > 0) { + gpxItem.chartHighlightPos = highlights[0].getX(); + } else { + gpxItem.chartHighlightPos = -1; + } + if (externalGestureListener != null) { + externalGestureListener.onChartGestureEnd(me, lastPerformedGesture, hasTranslated); + } + } + + @Override + public void onChartLongPressed(MotionEvent me) { + } + + @Override + public void onChartDoubleTapped(MotionEvent me) { + } + + @Override + public void onChartSingleTapped(MotionEvent me) { + } + + @Override + public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { + } + + @Override + public void onChartScale(MotionEvent me, float scaleX, float scaleY) { + } + + @Override + public void onChartTranslate(MotionEvent me, float dX, float dY) { + hasTranslated = true; + if (highlightDrawX != -1) { + Highlight h = mChart.getHighlightByTouchPoint(highlightDrawX, 0f); + if (h != null) { + /* + ILineDataSet set = mChart.getLineData().getDataSetByIndex(h.getDataSetIndex()); + if (set != null && set.isHighlightEnabled()) { + Entry e = set.getEntryForXValue(h.getX(), h.getY()); + MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), e.getY()); + h.setDraw((float) pix.x, (float) pix.y); + } + */ + mChart.highlightValue(h, true); + } + } + } + }); + } + + public void addValueSelectedListener(String key, ExternalValueSelectedListener listener) { + this.externalValueSelectedListeners.put(key, listener); + } + + public void removeValueSelectedListener(String key) { + this.externalValueSelectedListeners.remove(key); + } + + public void setExternalGestureListener(ExternalGestureListener listener) { + this.externalGestureListener = listener; + } + + @Override + public void updateView() { + GpxUiHelper.setupGPXChart(mChart, 4, 24f, 16f, !isNightMode(), true); + mChart.setData(mChartData); + updateHighlight(); + } + + @Override + public void highlight(Highlight h) { + super.highlight(h); + mChart.highlightValue(highlight); + } + + public GpxDisplayItem getGpxItem() { + return mAdditionalData; + } +} diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java new file mode 100644 index 0000000000..aded2e0fbe --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java @@ -0,0 +1,187 @@ +package net.osmand.plus.measurementtool.graph; + +import android.graphics.drawable.Drawable; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.StyleSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.graphics.ColorUtils; + +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; + +import net.osmand.AndroidUtils; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.SettingsNavigationActivity; +import net.osmand.plus.helpers.CustomBarChartRenderer; +import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.router.RouteStatisticsHelper; +import net.osmand.router.RouteStatisticsHelper.RouteStatistics; +import net.osmand.router.RouteStatisticsHelper.RouteSegmentAttribute; +import net.osmand.util.Algorithms; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CustomGraphAdapter extends BaseGraphAdapter { + + private static final int MINIMUM_CONTRAST_RATIO = 3; + + private String selectedPropertyName; + private ViewGroup legendContainer; + private LegendViewType legendViewType; + private LayoutChangeListener layoutChangeListener; + + public enum LegendViewType { + ONE_ELEMENT, + ALL_AS_LIST, + GONE + } + + public CustomGraphAdapter(HorizontalBarChart chart, boolean usedOnMap) { + super(chart, usedOnMap); + } + + @Override + protected void prepareCharterView() { + super.prepareCharterView(); + legendViewType = LegendViewType.GONE; + mChart.setRenderer(new CustomBarChartRenderer(mChart)); + mChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() { + @Override + public void onValueSelected(Entry e, Highlight h) { + if (getStatistics() == null) return; + + List elems = getStatistics().elements; + int i = h.getStackIndex(); + if (i >= 0 && elems.size() > i) { + selectedPropertyName = elems.get(i).getPropertyName(); + updateLegend(); + } + } + + @Override + public void onNothingSelected() { + selectedPropertyName = null; + updateLegend(); + } + }); + } + + @Override + public void updateView() { + mChart.clear(); + GpxUiHelper.setupHorizontalGPXChart(getMyApplication(), mChart, 5, 9, 24, true, isNightMode()); + mChart.setData(mChartData); + updateHighlight(); + updateLegend(); + } + + public void setLegendContainer(ViewGroup legendContainer) { + this.legendContainer = legendContainer; + } + + public void setLegendViewType(LegendViewType legendViewType) { + this.legendViewType = legendViewType; + } + + public void setLayoutChangeListener(LayoutChangeListener layoutChangeListener) { + this.layoutChangeListener = layoutChangeListener; + } + + public void highlight(Highlight h) { + super.highlight(h); + Highlight bh = h != null ? mChart.getHighlighter().getHighlight(1, h.getXPx()) : null; + if (bh != null) { + bh.setDraw(h.getXPx(), 0); + } + mChart.highlightValue(bh, true); + } + + private void updateLegend() { + if (legendContainer == null) return; + + legendContainer.removeAllViews(); + attachLegend(); + if (layoutChangeListener != null) { + layoutChangeListener.onLayoutChanged(); + } + } + + private void attachLegend() { + if (getSegmentsList() == null) return; + + switch (legendViewType) { + case ONE_ELEMENT: + for (RouteSegmentAttribute segment : getSegmentsList()) { + if (segment.getPropertyName().equals(selectedPropertyName)) { + attachLegend(Arrays.asList(segment), null); + break; + } + } + break; + case ALL_AS_LIST: + attachLegend(getSegmentsList(), selectedPropertyName); + break; + } + } + + private void attachLegend(List list, + String propertyNameToFullSpan) { + OsmandApplication app = getMyApplication(); + LayoutInflater inflater = LayoutInflater.from(app); + for (RouteStatisticsHelper.RouteSegmentAttribute segment : list) { + View view = inflater.inflate(R.layout.route_details_legend, legendContainer, false); + int segmentColor = segment.getColor(); + Drawable circle = app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, segmentColor); + ImageView legendIcon = (ImageView) view.findViewById(R.id.legend_icon_color); + legendIcon.setImageDrawable(circle); + double contrastRatio = ColorUtils.calculateContrast(segmentColor, + AndroidUtils.getColorFromAttr(app, R.attr.card_and_list_background_basic)); + if (contrastRatio < MINIMUM_CONTRAST_RATIO) { + legendIcon.setBackgroundResource(AndroidUtils.resolveAttribute(app, R.attr.bg_circle_contour)); + } + String propertyName = segment.getUserPropertyName(); + String name = SettingsNavigationActivity.getStringPropertyName(app, propertyName, propertyName.replaceAll("_", " ")); + boolean selected = segment.getPropertyName().equals(propertyNameToFullSpan); + Spannable text = getSpanLegend(name, segment, selected); + TextView legend = (TextView) view.findViewById(R.id.legend_text); + legend.setText(text); + + legendContainer.addView(view); + } + } + + private Spannable getSpanLegend(String title, + RouteSegmentAttribute segment, + boolean fullSpan) { + String formattedDistance = OsmAndFormatter.getFormattedDistance(segment.getDistance(), getMyApplication()); + title = Algorithms.capitalizeFirstLetter(title); + SpannableStringBuilder spannable = new SpannableStringBuilder(title); + spannable.append(": "); + int startIndex = fullSpan ? -0 : spannable.length(); + spannable.append(formattedDistance); + spannable.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), + startIndex, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return spannable; + } + + private List getSegmentsList() { + return getStatistics() != null ? new ArrayList<>(getStatistics().partition.values()) : null; + } + + private RouteStatistics getStatistics() { + return mAdditionalData; + } +} diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/GraphAdapterHelper.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/GraphAdapterHelper.java new file mode 100644 index 0000000000..efacad9d50 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/GraphAdapterHelper.java @@ -0,0 +1,145 @@ +package net.osmand.plus.measurementtool.graph; + +import android.annotation.SuppressLint; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.listener.ChartTouchListener; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; + +import java.util.List; + +public class GraphAdapterHelper { + + public static final String BIND_GRAPH_ADAPTERS_KEY = "bind_graph_adapters_key"; + public static final String BIND_TO_MAP_KEY = "bind_to_map_key"; + + public static void bindGraphAdapters(final CommonGraphAdapter mainGraphAdapter, + final List otherGraphAdapters, + final ViewGroup mainView) { + if (mainGraphAdapter == null || mainGraphAdapter.getChart() == null + || otherGraphAdapters == null || otherGraphAdapters.size() == 0) { + return; + } + + final LineChart mainChart = mainGraphAdapter.getChart(); + View.OnTouchListener mainChartTouchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent ev) { + if (mainView != null) { + mainView.requestDisallowInterceptTouchEvent(true); + } + for (BaseGraphAdapter adapter : otherGraphAdapters) { + if (adapter.getChart() != null) { + final MotionEvent event = MotionEvent.obtainNoHistory(ev); + event.setSource(0); + adapter.getChart().dispatchTouchEvent(event); + } + } + return false; + } + }; + mainChart.setOnTouchListener(mainChartTouchListener); + + mainGraphAdapter.addValueSelectedListener(BIND_GRAPH_ADAPTERS_KEY, + new CommonGraphAdapter.ExternalValueSelectedListener() { + @Override + public void onValueSelected(Entry e, Highlight h) { + for (BaseGraphAdapter adapter : otherGraphAdapters) { + adapter.highlight(h); + } + } + + @Override + public void onNothingSelected() { + for (BaseGraphAdapter adapter : otherGraphAdapters) { + adapter.highlight(null); + } + } + } + ); + + View.OnTouchListener otherChartsTouchListener = new View.OnTouchListener() { + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouch(View v, MotionEvent ev) { + if (ev.getSource() != 0) { + final MotionEvent event = MotionEvent.obtainNoHistory(ev); + event.setSource(0); + mainChart.dispatchTouchEvent(event); + return true; + } + return false; + } + }; + + for (BaseGraphAdapter adapter : otherGraphAdapters) { + if (adapter.getChart() != null) { + if (adapter.getChart() instanceof BarChart) { + // maybe we should find min and max axis from all charters + BarChart barChart = (BarChart) adapter.getChart(); + barChart.getAxisRight().setAxisMinimum(mainChart.getXChartMin()); + barChart.getAxisRight().setAxisMaximum(mainChart.getXChartMax()); + barChart.setHighlightPerDragEnabled(false); + barChart.setHighlightPerTapEnabled(false); + } + adapter.getChart().setOnTouchListener(otherChartsTouchListener); + } + } + } + + public static void bindToMap(final CommonGraphAdapter graphAdapter, + final MapActivity mapActivity, + final TrackDetailsMenu detailsMenu) { + graphAdapter.addValueSelectedListener(BIND_TO_MAP_KEY, + new CommonGraphAdapter.ExternalValueSelectedListener() { + + @Override + public void onValueSelected(Entry e, Highlight h) { + refreshChart(mapActivity, graphAdapter.getChart(), detailsMenu, false); + } + + @Override + public void onNothingSelected() { + } + }); + + graphAdapter.setExternalGestureListener(new CommonGraphAdapter.ExternalGestureListener() { + @Override + public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + } + + @Override + public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture, boolean hasTranslated) { + if ((lastPerformedGesture == ChartTouchListener.ChartGesture.DRAG && hasTranslated) || + lastPerformedGesture == ChartTouchListener.ChartGesture.X_ZOOM || + lastPerformedGesture == ChartTouchListener.ChartGesture.Y_ZOOM || + lastPerformedGesture == ChartTouchListener.ChartGesture.PINCH_ZOOM || + lastPerformedGesture == ChartTouchListener.ChartGesture.DOUBLE_TAP || + lastPerformedGesture == ChartTouchListener.ChartGesture.ROTATE) { + refreshChart(mapActivity, graphAdapter.getChart(), detailsMenu, true); + } + } + }); + } + + public static void refreshChart(MapActivity mapActivity, + LineChart chart, + TrackDetailsMenu menu, + boolean forceFit) { + if (mapActivity == null || chart == null || menu == null) return; + OsmandApplication app = mapActivity.getMyApplication(); + if (!app.getRoutingHelper().isFollowingMode()) { + menu.refreshChart(chart, forceFit); + mapActivity.refreshMap(); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java index 94b3f9bfa3..2fa80d9fa0 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java @@ -87,6 +87,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.ALTITUDE; +import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SPEED; + public class TrackSegmentFragment extends OsmAndListFragment implements TrackBitmapDrawerListener { private OsmandApplication app; @@ -425,64 +428,16 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit } } - private List getDataSets(GPXTabItemType tabType, LineChart chart) { + private List getDataSets(LineChart chart, + GPXTabItemType tabType, + GpxUiHelper.LineGraphType... types) { List dataSets = dataSetsMap.get(tabType); if (dataSets == null && chart != null) { - dataSets = new ArrayList<>(); GPXTrackAnalysis analysis = gpxItem.analysis; GpxDataItem gpxDataItem = getGpxDataItem(); boolean calcWithoutGaps = gpxItem.isGeneralTrack() && gpxDataItem != null && !gpxDataItem.isJoinSegments(); - switch (tabType) { - case GPX_TAB_ITEM_GENERAL: { - OrderedLineDataSet speedDataSet = null; - OrderedLineDataSet elevationDataSet = null; - if (analysis.hasSpeedData) { - speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, true, true, calcWithoutGaps); - } - if (analysis.hasElevationData) { - elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, false, true, calcWithoutGaps); - } - if (speedDataSet != null) { - dataSets.add(speedDataSet); - if (elevationDataSet != null) { - dataSets.add(elevationDataSet.getPriority() < speedDataSet.getPriority() - ? 1 : 0, elevationDataSet); - } - } else if (elevationDataSet != null) { - dataSets.add(elevationDataSet); - } - dataSetsMap.put(GPXTabItemType.GPX_TAB_ITEM_GENERAL, dataSets); - break; - } - case GPX_TAB_ITEM_ALTITUDE: { - OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, false, true, calcWithoutGaps); - if (elevationDataSet != null) { - dataSets.add(elevationDataSet); - } - if (analysis.hasElevationData) { - List eleValues = elevationDataSet != null && !gpxItem.isGeneralTrack() ? elevationDataSet.getValues() : null; - OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, eleValues, true, true, calcWithoutGaps); - if (slopeDataSet != null) { - dataSets.add(slopeDataSet); - } - } - dataSetsMap.put(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE, dataSets); - break; - } - case GPX_TAB_ITEM_SPEED: { - OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, false, true, calcWithoutGaps); - if (speedDataSet != null) { - dataSets.add(speedDataSet); - } - dataSetsMap.put(GPXTabItemType.GPX_TAB_ITEM_SPEED, dataSets); - break; - } - } + dataSets = GpxUiHelper.getDataSets(chart, app, analysis, calcWithoutGaps, types); + dataSetsMap.put(tabType, dataSets); } return dataSets; } @@ -703,7 +658,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit if (analysis != null) { if (analysis.hasElevationData || analysis.hasSpeedData) { GpxUiHelper.setupGPXChart(app, chart, 4); - chart.setData(new LineData(getDataSets(GPXTabItemType.GPX_TAB_ITEM_GENERAL, chart))); + chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_GENERAL, SPEED, ALTITUDE))); updateChart(chart); chart.setVisibility(View.VISIBLE); } else { @@ -821,7 +776,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit if (analysis != null) { if (analysis.hasElevationData) { GpxUiHelper.setupGPXChart(app, chart, 4); - chart.setData(new LineData(getDataSets(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE, chart))); + chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_ALTITUDE, ALTITUDE))); updateChart(chart); chart.setVisibility(View.VISIBLE); } else { @@ -923,7 +878,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit if (analysis != null && analysis.isSpeedSpecified()) { if (analysis.hasSpeedData) { GpxUiHelper.setupGPXChart(app, chart, 4); - chart.setData(new LineData(getDataSets(GPXTabItemType.GPX_TAB_ITEM_SPEED, chart))); + chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_SPEED, SPEED))); updateChart(chart); chart.setVisibility(View.VISIBLE); } else { @@ -1189,7 +1144,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit LatLon location = null; WptPt wpt = null; gpxItem.chartTypes = null; - List ds = getDataSets(tabType, null); + List ds = getDataSets(null, tabType); if (ds != null && ds.size() > 0) { gpxItem.chartTypes = new GPXDataSetType[ds.size()]; for (int i = 0; i < ds.size(); i++) { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java index 1f29dfd1b7..81c3f232d8 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java @@ -2,7 +2,6 @@ package net.osmand.plus.routepreparationmenu; import android.annotation.SuppressLint; import android.content.Context; -import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; @@ -14,11 +13,9 @@ import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.view.Gravity; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; -import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; @@ -30,15 +27,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; -import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; -import com.github.mikephil.charting.listener.ChartTouchListener.ChartGesture; -import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; -import com.github.mikephil.charting.utils.ViewPortHandler; import net.osmand.AndroidUtils; import net.osmand.GPXUtilities.GPXFile; @@ -68,10 +57,12 @@ import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; import net.osmand.plus.mapcontextmenu.CollapsableView; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; +import net.osmand.plus.measurementtool.graph.BaseGraphAdapter; +import net.osmand.plus.measurementtool.graph.CommonGraphAdapter; +import net.osmand.plus.measurementtool.graph.GraphAdapterHelper; import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; -import net.osmand.plus.routepreparationmenu.cards.CardChartListener; import net.osmand.plus.routepreparationmenu.cards.PublicTransportCard; import net.osmand.plus.routepreparationmenu.cards.PublicTransportCard.PublicTransportCardListener; import net.osmand.plus.routepreparationmenu.cards.RouteDirectionsCard; @@ -98,8 +89,8 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; -public class RouteDetailsFragment extends ContextMenuFragment implements PublicTransportCardListener, - CardListener, CardChartListener { +public class RouteDetailsFragment extends ContextMenuFragment + implements PublicTransportCardListener, CardListener { public static final String ROUTE_ID_KEY = "route_id_key"; private static final float PAGE_MARGIN = 5f; @@ -311,24 +302,7 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT return; } OsmandApplication app = mapActivity.getMyApplication(); - statisticCard = new RouteStatisticCard(mapActivity, gpx, new OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent ev) { - LinearLayout mainView = getMainView(); - if (mainView != null) { - mainView.requestDisallowInterceptTouchEvent(true); - } - for (RouteInfoCard card : routeInfoCards) { - final HorizontalBarChart ch = card.getChart(); - if (ch != null) { - final MotionEvent event = MotionEvent.obtainNoHistory(ev); - event.setSource(0); - ch.dispatchTouchEvent(event); - } - } - return false; - } - }, new OnClickListener() { + statisticCard = new RouteStatisticCard(mapActivity, gpx, new OnClickListener() { @Override public void onClick(View v) { openDetails(); @@ -336,7 +310,6 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT }); statisticCard.setTransparentBackground(true); statisticCard.setListener(this); - statisticCard.setChartListener(this); menuCards.add(statisticCard); cardsContainer.addView(statisticCard.build(mapActivity)); buildRowDivider(cardsContainer, false); @@ -359,13 +332,25 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT routeDetailsMenu.setGpxItem(gpxItem); } routeDetailsMenu.setMapActivity(mapActivity); - LineChart chart = statisticCard.getChart(); - if (chart != null) { - chart.setExtraRightOffset(16); - chart.setExtraLeftOffset(16); + + CommonGraphAdapter mainGraphAdapter = statisticCard.getGraphAdapter(); + if (mainGraphAdapter != null) { + GraphAdapterHelper.bindGraphAdapters(mainGraphAdapter, getRouteInfoCardsGraphAdapters(), getMainView()); + GraphAdapterHelper.bindToMap(mainGraphAdapter, mapActivity, routeDetailsMenu); } } + private List getRouteInfoCardsGraphAdapters() { + List adapters = new ArrayList<>(); + for (RouteInfoCard card : routeInfoCards) { + BaseGraphAdapter adapter = card.getGraphAdapter(); + if (adapter != null) { + adapters.add(adapter); + } + } + return adapters; + } + public static List calculateRouteStatistics(OsmandApplication app, List route, boolean nightMode) { @@ -384,7 +369,12 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT protected void calculateLayout(View view, boolean initLayout) { super.calculateLayout(view, initLayout); if (!initLayout && getCurrentMenuState() != MenuState.FULL_SCREEN) { - refreshChart(false); + MapActivity mapActivity = getMapActivity(); + CommonGraphAdapter mainGraphAdapter = statisticCard.getGraphAdapter(); + if (mainGraphAdapter != null) { + LineChart chart = mainGraphAdapter.getChart(); + GraphAdapterHelper.refreshChart(mapActivity, chart, routeDetailsMenu, false); + } } } @@ -401,48 +391,15 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT buildRowDivider(cardsContainer, false); } - private OnTouchListener getChartTouchListener() { - return new OnTouchListener() { - @SuppressLint("ClickableViewAccessibility") - @Override - public boolean onTouch(View v, MotionEvent ev) { - if (ev.getSource() != 0 && v instanceof HorizontalBarChart) { - if (statisticCard != null) { - LineChart ch = statisticCard.getChart(); - if (ch != null) { - final MotionEvent event = MotionEvent.obtainNoHistory(ev); - event.setSource(0); - ch.dispatchTouchEvent(event); - } - } - return true; - } - return false; - } - }; - } - @SuppressLint("ClickableViewAccessibility") - private void addRouteCard(final LinearLayout cardsContainer, RouteInfoCard routeInfoCard) { + private void addRouteCard(LinearLayout cardsContainer, + RouteInfoCard routeInfoCard) { OsmandApplication app = requireMyApplication(); menuCards.add(routeInfoCard); routeInfoCard.setListener(this); cardsContainer.addView(routeInfoCard.build(app)); buildRowDivider(cardsContainer, false); - routeInfoCards.add(routeInfoCard); - HorizontalBarChart chart = routeInfoCard.getChart(); - if (chart != null) { - LineChart mainChart = statisticCard.getChart(); - if (mainChart != null) { - chart.getAxisRight().setAxisMinimum(mainChart.getXChartMin()); - chart.getAxisRight().setAxisMaximum(mainChart.getXChartMax()); - } - chart.setRenderer(new CustomBarChartRenderer(chart, chart.getAnimator(), chart.getViewPortHandler(), AndroidUtils.dpToPx(app, 1f) / 2f)); - chart.setHighlightPerDragEnabled(false); - chart.setHighlightPerTapEnabled(false); - chart.setOnTouchListener(getChartTouchListener()); - } } public Drawable getCollapseIcon(boolean collapsed) { @@ -1615,59 +1572,6 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT } } - private void refreshChart(boolean forceFit) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null && routeDetailsMenu != null && statisticCard != null && - !mapActivity.getMyApplication().getRoutingHelper().isFollowingMode()) { - LineChart chart = statisticCard.getChart(); - if (chart != null) { - routeDetailsMenu.refreshChart(chart, forceFit); - mapActivity.refreshMap(); - } - } - } - - private void highlightRouteInfoCharts(@Nullable Highlight h) { - for (RouteInfoCard rc : routeInfoCards) { - HorizontalBarChart chart = rc.getChart(); - if (chart != null) { - Highlight bh = h != null ? chart.getHighlighter().getHighlight(1, h.getXPx()) : null; - if (bh != null) { - bh.setDraw(h.getXPx(), 0); - } - chart.highlightValue(bh, true); - } - } - } - - @Override - public void onValueSelected(BaseCard card, Entry e, Highlight h) { - refreshChart(false); - highlightRouteInfoCharts(h); - } - - @Override - public void onNothingSelected(BaseCard card) { - highlightRouteInfoCharts(null); - } - - @Override - public void onChartGestureStart(BaseCard card, MotionEvent me, ChartGesture lastPerformedGesture) { - } - - @Override - public void onChartGestureEnd(BaseCard card, MotionEvent me, ChartGesture lastPerformedGesture, boolean hasTranslated) { - if ((lastPerformedGesture == ChartGesture.DRAG && hasTranslated) || - lastPerformedGesture == ChartGesture.X_ZOOM || - lastPerformedGesture == ChartGesture.Y_ZOOM || - lastPerformedGesture == ChartGesture.PINCH_ZOOM || - lastPerformedGesture == ChartGesture.DOUBLE_TAP || - lastPerformedGesture == ChartGesture.ROTATE) { - - refreshChart(true); - } - } - public static class CumulativeInfo { public int distance; public int time; @@ -1696,20 +1600,4 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT final int timeInSeconds = model.getExpectedTime(); return Algorithms.formatDuration(timeInSeconds, app.accessibilityEnabled()); } - - private static class CustomBarChartRenderer extends HorizontalBarChartRenderer { - - private float highlightHalfWidth; - - CustomBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler, float highlightHalfWidth) { - super(chart, animator, viewPortHandler); - this.highlightHalfWidth = highlightHalfWidth; - } - - @Override - protected void setHighlightDrawPos(Highlight high, RectF bar) { - bar.left = high.getDrawX() - highlightHalfWidth; - bar.right = high.getDrawX() + highlightHalfWidth; - } - } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java index 245412fe34..d4101e58ec 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java @@ -31,7 +31,6 @@ public abstract class BaseCard { protected boolean nightMode; private CardListener listener; - private CardChartListener chartListener; public interface CardListener { void onCardLayoutNeeded(@NonNull BaseCard card); @@ -78,14 +77,6 @@ public abstract class BaseCard { this.listener = listener; } - public CardChartListener getChartListener() { - return chartListener; - } - - public void setChartListener(CardChartListener chartListener) { - this.chartListener = chartListener; - } - public void setLayoutNeeded() { CardListener listener = this.listener; if (listener != null) { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java index ef02b16734..d50f0dfdc8 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java @@ -1,55 +1,33 @@ package net.osmand.plus.routepreparationmenu.cards; import android.graphics.drawable.Drawable; -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.text.style.StyleSpan; -import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import androidx.annotation.Nullable; -import androidx.appcompat.view.ContextThemeWrapper; -import androidx.core.content.ContextCompat; -import androidx.core.graphics.ColorUtils; - import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import net.osmand.GPXUtilities.GPXTrackAnalysis; -import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.SettingsBaseActivity; -import net.osmand.plus.activities.SettingsNavigationActivity; import net.osmand.plus.helpers.GpxUiHelper; -import net.osmand.router.RouteStatisticsHelper.RouteSegmentAttribute; +import net.osmand.plus.measurementtool.graph.CustomGraphAdapter; +import net.osmand.plus.measurementtool.graph.CustomGraphAdapter.LegendViewType; import net.osmand.router.RouteStatisticsHelper.RouteStatistics; -import net.osmand.util.Algorithms; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; public class RouteInfoCard extends BaseCard { - - private static final int MINIMUM_CONTRAST_RATIO = 3; - - private RouteStatistics routeStatistics; + private RouteStatistics statistics; private GPXTrackAnalysis analysis; - private String selectedPropertyName; + private CustomGraphAdapter graphAdapter; private boolean showLegend; - public RouteInfoCard(MapActivity mapActivity, RouteStatistics routeStatistics, GPXTrackAnalysis analysis) { + public RouteInfoCard(MapActivity mapActivity, RouteStatistics statistics, GPXTrackAnalysis analysis) { super(mapActivity); - this.routeStatistics = routeStatistics; + this.statistics = statistics; this.analysis = analysis; } @@ -60,112 +38,46 @@ public class RouteInfoCard extends BaseCard { @Override protected void updateContent() { - updateContent(routeStatistics); - } - - @Nullable - public HorizontalBarChart getChart() { - return (HorizontalBarChart) view.findViewById(R.id.chart); - } - - private void updateContent(final RouteStatistics routeStatistics) { updateHeader(); - final HorizontalBarChart chart = (HorizontalBarChart) view.findViewById(R.id.chart); - GpxUiHelper.setupHorizontalGPXChart(app, chart, 5, 9, 24, true, nightMode); - chart.setExtraRightOffset(16); - chart.setExtraLeftOffset(16); - BarData barData = GpxUiHelper.buildStatisticChart(app, chart, routeStatistics, analysis, true, nightMode); - chart.setData(barData); - chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() { - @Override - public void onValueSelected(Entry e, Highlight h) { - List elems = routeStatistics.elements; - int i = h.getStackIndex(); - if (i >= 0 && elems.size() > i) { - selectedPropertyName = elems.get(i).getPropertyName(); - if (showLegend) { - updateLegend(routeStatistics); - } - } - } - - @Override - public void onNothingSelected() { - selectedPropertyName = null; - if (showLegend) { - updateLegend(routeStatistics); - } - } - }); LinearLayout container = (LinearLayout) view.findViewById(R.id.route_items); - container.removeAllViews(); - if (showLegend) { - attachLegend(container, routeStatistics); - } - final ImageView iconViewCollapse = (ImageView) view.findViewById(R.id.up_down_icon); - iconViewCollapse.setImageDrawable(getCollapseIcon(!showLegend)); + HorizontalBarChart chart = (HorizontalBarChart) view.findViewById(R.id.chart); + BarData barData = GpxUiHelper.buildStatisticChart(app, chart, statistics, analysis, true, nightMode); + graphAdapter = new CustomGraphAdapter(chart, true); + graphAdapter.setLegendContainer(container); + graphAdapter.updateData(barData, statistics); + updateView(); + view.findViewById(R.id.info_type_details_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showLegend = !showLegend; - updateContent(); + updateView(); setLayoutNeeded(); } }); } - protected void updateLegend(RouteStatistics routeStatistics) { - LinearLayout container = (LinearLayout) view.findViewById(R.id.route_items); - container.removeAllViews(); - attachLegend(container, routeStatistics); - setLayoutNeeded(); - } - - private Drawable getCollapseIcon(boolean collapsed) { - return collapsed ? getContentIcon(R.drawable.ic_action_arrow_down) : getActiveIcon(R.drawable.ic_action_arrow_up); + private void updateView() { + updateCollapseIcon(); + graphAdapter.setLegendViewType(showLegend ? LegendViewType.ALL_AS_LIST : LegendViewType.GONE); + graphAdapter.updateView(); } private void updateHeader() { TextView title = (TextView) view.findViewById(R.id.info_type_title); - String name = SettingsBaseActivity.getStringRouteInfoPropertyValue(app, routeStatistics.name); + String name = SettingsBaseActivity.getStringRouteInfoPropertyValue(app, statistics.name); title.setText(name); } - private void attachLegend(ViewGroup container, RouteStatistics routeStatistics) { - Map partition = routeStatistics.partition; - List> list = new ArrayList<>(partition.entrySet()); - ContextThemeWrapper ctx = new ContextThemeWrapper(mapActivity, !nightMode ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme); - LayoutInflater inflater = LayoutInflater.from(ctx); - for (Map.Entry entry : list) { - RouteSegmentAttribute segment = entry.getValue(); - View view = inflater.inflate(R.layout.route_details_legend, container, false); - int segmentColor = segment.getColor(); - Drawable circle = app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, segmentColor); - ImageView legendIcon = (ImageView) view.findViewById(R.id.legend_icon_color); - legendIcon.setImageDrawable(circle); - double contrastRatio = ColorUtils.calculateContrast(segmentColor, ContextCompat.getColor(app, nightMode ? R.color.card_and_list_background_dark : R.color.card_and_list_background_light)); - if (contrastRatio < MINIMUM_CONTRAST_RATIO) { - legendIcon.setBackgroundResource(nightMode ? R.drawable.circle_contour_bg_dark : R.drawable.circle_contour_bg_light); - } - String propertyName = segment.getUserPropertyName(); - String name = SettingsNavigationActivity.getStringPropertyName(app, propertyName, propertyName.replaceAll("_", " ")); - Spannable text = getSpanLegend(name, segment, segment.getUserPropertyName().equals(selectedPropertyName)); - TextView legend = (TextView) view.findViewById(R.id.legend_text); - legend.setText(text); - - container.addView(view); - } + private void updateCollapseIcon() { + ImageView ivCollapse = (ImageView) view.findViewById(R.id.up_down_icon); + Drawable drawable = showLegend ? + getContentIcon(R.drawable.ic_action_arrow_down) : + getActiveIcon(R.drawable.ic_action_arrow_up); + ivCollapse.setImageDrawable(drawable); } - private Spannable getSpanLegend(String title, RouteSegmentAttribute segment, boolean selected) { - String formattedDistance = OsmAndFormatter.getFormattedDistance(segment.getDistance(), getMyApplication()); - title = Algorithms.capitalizeFirstLetter(title); - SpannableStringBuilder spannable = new SpannableStringBuilder(title); - spannable.append(": "); - int startIndex = selected ? -0 : spannable.length(); - spannable.append(formattedDistance); - spannable.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), startIndex, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - - return spannable; + public CustomGraphAdapter getGraphAdapter() { + return graphAdapter; } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java index ef37797f0a..bb6483155b 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java @@ -1,13 +1,10 @@ package net.osmand.plus.routepreparationmenu.cards; -import android.graphics.Matrix; import android.os.Build; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; -import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; -import android.view.View.OnTouchListener; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -16,18 +13,12 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.listener.ChartTouchListener.ChartGesture; -import com.github.mikephil.charting.listener.OnChartGestureListener; -import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import net.osmand.AndroidUtils; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXTrackAnalysis; -import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; @@ -36,6 +27,7 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; +import net.osmand.plus.measurementtool.graph.CommonGraphAdapter; import net.osmand.plus.routing.RoutingHelper; import java.util.ArrayList; @@ -52,16 +44,15 @@ public class RouteStatisticCard extends BaseCard { private OrderedLineDataSet slopeDataSet; @Nullable private OrderedLineDataSet elevationDataSet; - private OnTouchListener onTouchListener; private OnClickListener onAnalyseClickListener; + private CommonGraphAdapter graphAdapter; - public RouteStatisticCard(MapActivity mapActivity, GPXFile gpx, OnTouchListener onTouchListener, + public RouteStatisticCard(MapActivity mapActivity, GPXFile gpx, OnClickListener onAnalyseClickListener) { super(mapActivity); this.gpx = gpx; - this.onTouchListener = onTouchListener; this.onAnalyseClickListener = onAnalyseClickListener; - makeGpxDisplayItem(); + this.gpxItem = GpxUiHelper.makeGpxDisplayItem(app, gpx); } @Nullable @@ -219,26 +210,14 @@ public class RouteStatisticCard extends BaseCard { return elevationDataSet; } - private void makeGpxDisplayItem() { - String groupName = getMyApplication().getString(R.string.current_route); - GpxSelectionHelper.GpxDisplayGroup group = getMyApplication().getSelectedGpxHelper().buildGpxDisplayGroup(gpx, 0, groupName); - if (group != null && group.getModifiableList().size() > 0) { - gpxItem = group.getModifiableList().get(0); - if (gpxItem != null) { - gpxItem.route = true; - } - } - } - @Nullable - public LineChart getChart() { - return (LineChart) view.findViewById(R.id.chart); + public CommonGraphAdapter getGraphAdapter() { + return graphAdapter; } private void buildHeader(GPXTrackAnalysis analysis) { - final LineChart mChart = (LineChart) view.findViewById(R.id.chart); - GpxUiHelper.setupGPXChart(mChart, 4, 24f, 16f, !nightMode, true); - mChart.setOnTouchListener(onTouchListener); + LineChart mChart = (LineChart) view.findViewById(R.id.chart); + graphAdapter = new CommonGraphAdapter(mChart, true); if (analysis.hasElevationData) { List dataSets = new ArrayList<>(); @@ -256,99 +235,7 @@ public class RouteStatisticCard extends BaseCard { this.elevationDataSet = elevationDataSet; this.slopeDataSet = slopeDataSet; - LineData data = new LineData(dataSets); - mChart.setData(data); - - mChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() { - @Override - public void onValueSelected(Entry e, Highlight h) { - CardChartListener chartListener = getChartListener(); - if (chartListener != null) { - chartListener.onValueSelected(RouteStatisticCard.this, e, h); - } - } - - @Override - public void onNothingSelected() { - CardChartListener chartListener = getChartListener(); - if (chartListener != null) { - chartListener.onNothingSelected(RouteStatisticCard.this); - } - } - }); - - mChart.setOnChartGestureListener(new OnChartGestureListener() { - boolean hasTranslated = false; - float highlightDrawX = -1; - - @Override - public void onChartGestureStart(MotionEvent me, ChartGesture lastPerformedGesture) { - hasTranslated = false; - if (mChart.getHighlighted() != null && mChart.getHighlighted().length > 0) { - highlightDrawX = mChart.getHighlighted()[0].getDrawX(); - } else { - highlightDrawX = -1; - } - CardChartListener chartListener = getChartListener(); - if (chartListener != null) { - chartListener.onChartGestureStart(RouteStatisticCard.this, me, lastPerformedGesture); - } - } - - @Override - public void onChartGestureEnd(MotionEvent me, ChartGesture lastPerformedGesture) { - gpxItem.chartMatrix = new Matrix(mChart.getViewPortHandler().getMatrixTouch()); - Highlight[] highlights = mChart.getHighlighted(); - if (highlights != null && highlights.length > 0) { - gpxItem.chartHighlightPos = highlights[0].getX(); - } else { - gpxItem.chartHighlightPos = -1; - } - CardChartListener chartListener = getChartListener(); - if (chartListener != null) { - chartListener.onChartGestureEnd(RouteStatisticCard.this, me, lastPerformedGesture, hasTranslated); - } - } - - @Override - public void onChartLongPressed(MotionEvent me) { - } - - @Override - public void onChartDoubleTapped(MotionEvent me) { - } - - @Override - public void onChartSingleTapped(MotionEvent me) { - } - - @Override - public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { - } - - @Override - public void onChartScale(MotionEvent me, float scaleX, float scaleY) { - } - - @Override - public void onChartTranslate(MotionEvent me, float dX, float dY) { - hasTranslated = true; - if (highlightDrawX != -1) { - Highlight h = mChart.getHighlightByTouchPoint(highlightDrawX, 0f); - if (h != null) { - /* - ILineDataSet set = mChart.getLineData().getDataSetByIndex(h.getDataSetIndex()); - if (set != null && set.isHighlightEnabled()) { - Entry e = set.getEntryForXValue(h.getX(), h.getY()); - MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), e.getY()); - h.setDraw((float) pix.x, (float) pix.y); - } - */ - mChart.highlightValue(h, true); - } - } - } - }); + graphAdapter.fullUpdate(new LineData(dataSets), gpxItem); mChart.setVisibility(View.VISIBLE); } else { mChart.setVisibility(View.GONE); From e9a1bad5abfbcaf8924b52b8a1774fd9472cf2c0 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Fri, 30 Oct 2020 22:51:30 +0200 Subject: [PATCH 004/106] Import voice --- .../backend/backup/FileSettingsItem.java | 17 +++++------------ .../backend/backup/SettingsExporter.java | 4 ++-- .../settings/backend/backup/SettingsHelper.java | 3 --- .../backend/backup/SettingsImporter.java | 3 ++- .../settings/backend/backup/SettingsItem.java | 3 ++- .../backend/backup/SettingsItemReader.java | 11 +++++++++++ 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index 151aaf61f6..bb66ad06d0 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -21,8 +21,6 @@ import java.io.OutputStream; public class FileSettingsItem extends StreamSettingsItem { - - public enum FileSubtype { UNKNOWN("", null), OTHER("other", ""), @@ -50,6 +48,10 @@ public class FileSettingsItem extends StreamSettingsItem { return this == OBF_MAP || this == WIKI_MAP || this == SRTM_MAP; } + public boolean isDirectory() { + return this == TTS_VOICE || this == VOICE; + } + public String getSubtypeName() { return subtypeName; } @@ -123,7 +125,6 @@ public class FileSettingsItem extends StreamSettingsItem { private final File appPath; protected FileSubtype subtype; private long size; - private boolean subFolders; public FileSettingsItem(@NonNull OsmandApplication app, @NonNull File file) throws IllegalArgumentException { super(app, file.getPath().replace(app.getAppPath(null).getPath(), "")); @@ -210,14 +211,6 @@ public class FileSettingsItem extends StreamSettingsItem { this.size = size; } - public boolean isSubFolders() { - return subFolders; - } - - public void setSubFolders(boolean subFolders) { - this.subFolders = subFolders; - } - @NonNull public File getFile() { return file; @@ -253,7 +246,7 @@ public class FileSettingsItem extends StreamSettingsItem { @Override public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { OutputStream output; - File dest = FileSettingsItem.this.file; + File dest = getDestination(); if (dest.exists() && !shouldReplace) { dest = renameFile(dest); } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java index 88809ea937..88b7851630 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java @@ -68,7 +68,7 @@ class SettingsExporter { if (Algorithms.isEmpty(fileName)) { fileName = item.getDefaultFileName(); } - if (item instanceof FileSettingsItem && ((FileSettingsItem) item).isSubFolders()) { + if (item instanceof FileSettingsItem && ((FileSettingsItem) item).getSubtype().isDirectory()) { File file = ((FileSettingsItem) item).getFile(); zipDirsWithFiles(file, writer, zos); } else { @@ -97,7 +97,7 @@ class SettingsExporter { FileSettingsItem item = (FileSettingsItem) writer.getItem(); String zipEntryName = Algorithms.isEmpty(item.getSubtype().getSubtypeFolder()) ? f.getName() - : f.getPath().substring(f.getPath().indexOf(item.getSubtype().getSubtypeFolder())); + : f.getPath().substring(f.getPath().indexOf(item.getSubtype().getSubtypeFolder()) - 1); ZipEntry entry = new ZipEntry(zipEntryName); zos.putNextEntry(entry); item.setInputStream(new FileInputStream(f)); 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 0af0aa08b8..218d1a1f16 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -610,9 +610,6 @@ public class SettingsHelper { try { FileSettingsItem fileItem = new FileSettingsItem(app, (File) object); settingsItems.add(fileItem); - if (FileSubtype.getSubtypeByPath(app, ((File) object).getPath()) == FileSubtype.VOICE) { - fileItem.setSubFolders(true); - } } catch (IllegalArgumentException e) { LOG.warn("Trying to export unsuported file type", e); } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java index a03f363542..f1a6f2d894 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java @@ -25,7 +25,7 @@ import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT; class SettingsImporter { - private OsmandApplication app; + private final OsmandApplication app; SettingsImporter(@NonNull OsmandApplication app) { this.app = app; @@ -124,6 +124,7 @@ class SettingsImporter { try { SettingsItemReader reader = item.getReader(); if (reader != null) { + reader.setDestination(app.getAppPath(fileName)); reader.readFromStream(ois); } } catch (IllegalArgumentException e) { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java index e54cc99409..301c4f8882 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java @@ -12,6 +12,7 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -88,7 +89,7 @@ public abstract class SettingsItem { public boolean applyFileName(@NonNull String fileName) { String n = getFileName(); - return n != null && (n.endsWith(fileName) || fileName.startsWith(n)); + return n != null && (n.endsWith(fileName) || fileName.startsWith(n + File.separator)); } public boolean shouldReadOnCollecting() { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java index daa66f979a..5269150adc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java @@ -2,6 +2,7 @@ package net.osmand.plus.settings.backend.backup; import androidx.annotation.NonNull; +import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -9,9 +10,19 @@ public abstract class SettingsItemReader { private T item; + File destination; + public SettingsItemReader(@NonNull T item) { this.item = item; } + public void setDestination(File destination) { + this.destination = destination; + } + + public File getDestination() { + return destination; + } + public abstract void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException; } From 1878e861bcf715f919ff07a5a4ce5915dfde744f Mon Sep 17 00:00:00 2001 From: Hakim Oubouali Date: Sat, 31 Oct 2020 10:07:24 +0100 Subject: [PATCH 005/106] Added translation using Weblate (Central Atlas Tamazight) --- OsmAnd-telegram/res/values-tzm/strings.xml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 OsmAnd-telegram/res/values-tzm/strings.xml diff --git a/OsmAnd-telegram/res/values-tzm/strings.xml b/OsmAnd-telegram/res/values-tzm/strings.xml new file mode 100644 index 0000000000..a6b3daec93 --- /dev/null +++ b/OsmAnd-telegram/res/values-tzm/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file From 0dd91acbc3f194ff181f8b459c9639ceeb94cc82 Mon Sep 17 00:00:00 2001 From: ffff23 Date: Fri, 30 Oct 2020 16:33:47 +0000 Subject: [PATCH 006/106] Translated using Weblate (Japanese) Currently translated at 97.8% (3446 of 3521 strings) --- OsmAnd/res/values-ja/strings.xml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/OsmAnd/res/values-ja/strings.xml b/OsmAnd/res/values-ja/strings.xml index be920969b3..c189909e5a 100644 --- a/OsmAnd/res/values-ja/strings.xml +++ b/OsmAnd/res/values-ja/strings.xml @@ -827,7 +827,7 @@ POIの更新は利用できません ヘルプ アクセシビリティモード アクセシビリティ(ユーザー補助)機能を設定します - ON + On OFF デバイス側のユーザー補助設定に従う メニューに戻る @@ -1547,7 +1547,7 @@ POIの更新は利用できません マップストレージ コピー OSMの編集を削除 - 無効化 + 無効 ログオフ 国境を越えて別の国に入るようなルート設定を避けます。 高さ制限 @@ -2853,7 +2853,7 @@ POIの更新は利用できません %1$s を利用 道路種別 入れ替え - 詳細を見る + さらに表示 マップ上の経路 GPX経路の表示/非表示 マップ上にある選択したGPX経路の表示/非表示を切り替えるボタンです。 @@ -2898,7 +2898,7 @@ POIの更新は利用できません %1$.2f %2$s 支払い方法の選択: 寄付金はOSMの地図製作に役立てられます。 - 360°イメージのみ表示 + 360°画像のみを表示 編集 %1$s, 合計 %2$s mBTC 起動 グアラニー語 @@ -3048,9 +3048,9 @@ POIの更新は利用できません マップ上に低排出ゾーン(CO2排出量の多い車両に課税するエリア)を表示します。ルーティングには影響しません。 低排出ゾーンの表示 デフォルト - 出口: + 降車 %1$d回の乗り換え - 歩行 + 徒歩 ログの送信 %1$d個のファイルを移動しました。(%2$s) %1$d個のファイルをコピーしました。(%2$s) @@ -3106,12 +3106,12 @@ POIの更新は利用できません 開始時に表示するプロファイルの選択 カスタムプロファイルは標準のアプリケーションプロファイルを元に作成します。ウィジェットなどの表示設定や速度と距離の単位などの標準設定をプロファイルごとに定義可能です。これらは標準のアプリプロファイルを基本としており、今後それらと共に拡張される可能性があります: ナビゲーションタイプの選択 - 乗用車,トラック,オートバイ - マウンテンバイク、モペッド(ペダル付き原動機付自転車)、馬 - 徒歩,ハイキング,ランニング + 乗用車、トラック、オートバイ + マウンテンバイク、モペッド、馬 + 徒歩、ハイキング、ランニング 公共交通機関の種類 - エンジン付き船舶,漕ぎボート,帆船 - 航空機,グライダー + 船舶、漕ぎボート、帆船 + 航空機、グライダー ジオコーディング 直線 BRouter(オフライン) From 5e0e228a502661935d95538f028e2bd1a4d5f001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=BB=D0=B0=D0=BC=D0=B5=D0=BD?= Date: Sat, 31 Oct 2020 07:43:22 +0000 Subject: [PATCH 007/106] Translated using Weblate (Bulgarian) Currently translated at 46.7% (1647 of 3521 strings) --- OsmAnd/res/values-bg/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-bg/strings.xml b/OsmAnd/res/values-bg/strings.xml index 8a5ad86232..813e23367c 100644 --- a/OsmAnd/res/values-bg/strings.xml +++ b/OsmAnd/res/values-bg/strings.xml @@ -2186,4 +2186,5 @@ Спорт Аварийни служби Пътуване + Изчистете маркера OAuth на OpenStreetMap \ No newline at end of file From 0d29f19ae015aa26d55b89cafed962d438a0c30b Mon Sep 17 00:00:00 2001 From: Ajeje Brazorf Date: Fri, 30 Oct 2020 19:56:06 +0000 Subject: [PATCH 008/106] Translated using Weblate (Sardinian) Currently translated at 99.5% (3505 of 3521 strings) --- OsmAnd/res/values-sc/strings.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/OsmAnd/res/values-sc/strings.xml b/OsmAnd/res/values-sc/strings.xml index 8c9aa3a3ec..2245af22f2 100644 --- a/OsmAnd/res/values-sc/strings.xml +++ b/OsmAnd/res/values-sc/strings.xml @@ -3932,4 +3932,11 @@ Iseta su càrculu nou de s\'àndala. \nSu gràficu at a èssere a disponimentu a pustis de su càrculu. %1$s — %2$s + Apretu/Emergèntzia + Ispetziales + Trasportu + Servìtziu + Sìmbulos + Isport + Biàgiu \ No newline at end of file From 8e81a76948b798deff9f2cba06bfbd8d6cafd320 Mon Sep 17 00:00:00 2001 From: Franco Date: Fri, 30 Oct 2020 12:27:47 +0000 Subject: [PATCH 009/106] Translated using Weblate (Spanish (Argentina)) Currently translated at 99.9% (3520 of 3521 strings) --- OsmAnd/res/values-es-rAR/strings.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index ad60cd64f0..54e7d2a41b 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -3829,7 +3829,7 @@ Ruta inversa Recalcular sólo el siguiente segmento usando el perfil elegido. Recalcular toda la traza usando el perfil elegido. - Marca cómo conectar los puntos, con una línea recta o calcular una ruta entre ellos como se detalla a continuación. + Elige cómo conectar los puntos, con una línea recta o calcular una ruta entre ellos como se detalla a continuación. Traza completa Siguiente segmento A continuación, ajusta la traza al camino permitido más cercano con un perfil de navegación. @@ -3937,4 +3937,13 @@ Espera el recálculo de la ruta. \nEl gráfico estará disponible después del recálculo. %1$s — %2$s + Mapas locales + Comodidad + Especial + Transporte + Servicio + Símbolos + Deporte + Emergencia + Viaje \ No newline at end of file From 15562f947a903a7753452cb690307b1218a40688 Mon Sep 17 00:00:00 2001 From: Franco Date: Fri, 30 Oct 2020 12:34:36 +0000 Subject: [PATCH 010/106] Translated using Weblate (Spanish (Argentina)) Currently translated at 100.0% (3829 of 3829 strings) --- OsmAnd/res/values-es-rAR/phrases.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-es-rAR/phrases.xml b/OsmAnd/res/values-es-rAR/phrases.xml index 4a15cc5cdd..9f3c0b8803 100644 --- a/OsmAnd/res/values-es-rAR/phrases.xml +++ b/OsmAnd/res/values-es-rAR/phrases.xml @@ -3811,7 +3811,7 @@ Contrastado Primitivo Incorrecto - Señal para encontrar el poste + Conexión a Internet: clientes Nivel del agua: parcialmente sumergido Nivel del agua: sumergido Nivel de agua: seco @@ -3852,4 +3852,8 @@ Panal de abejas Frutos secos Gas natural licuado + Apartadero + Cobertizos + Azotea + Punto GPX \ No newline at end of file From 495fcc298b6c74c8caef5cabdcf6457331c72231 Mon Sep 17 00:00:00 2001 From: Verdulo Date: Fri, 30 Oct 2020 19:38:41 +0000 Subject: [PATCH 011/106] Translated using Weblate (Esperanto) Currently translated at 99.9% (3520 of 3521 strings) --- OsmAnd/res/values-eo/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index c469f7f4bd..9e3cd983c5 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -3934,4 +3934,13 @@ \nDiagramo estos videbla post rekalkulado. %1$s — %2$s Manko + Lokaj mapoj + Oportunaĵo + Specialaj + Transporto + Servo + Simboloj + Sporto + Vivsavo + Vojaĝo \ No newline at end of file From 45a06ce372365ff7687d2eb2af14802b9a499013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sveinn=20=C3=AD=20Felli?= Date: Fri, 30 Oct 2020 13:45:40 +0000 Subject: [PATCH 012/106] Translated using Weblate (Icelandic) Currently translated at 100.0% (3521 of 3521 strings) --- OsmAnd/res/values-is/strings.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/OsmAnd/res/values-is/strings.xml b/OsmAnd/res/values-is/strings.xml index 3414adba28..0682b0030e 100644 --- a/OsmAnd/res/values-is/strings.xml +++ b/OsmAnd/res/values-is/strings.xml @@ -106,15 +106,15 @@ Veldu flokk Hraðaeining sml - sjómílur - kílómetrar á klukkustund - mílur á klukkustund - metrar á sekúndu - mínútur á kílómetra - mínútur á mílu + Sjómílur + Kílómetrar á klukkustund + Mílur á klukkustund + Metrar á sekúndu + Mínútur á kílómetra + Mínútur á mílu Sjómílur á klukkustund (hnútar) hnútar - mín/m + mín/ml mín/km m/sek Leiðsögn @@ -238,7 +238,7 @@ Sýna allt Fella saman Birta á korti - Kort + Landakort Eftirlæti Eftirlæti Heimilisfang @@ -2109,7 +2109,7 @@ Nafnið inniheldur of marga hástafi. Viltu halda áfram? Tvítekið nafn á flýtiaðgerð Flokkur til að vista eftirlætisstað í: - Setja inn + Setja upp Ljósmyndir á netinu Engar myndir hér. Breyttu leitarorðum eða stækkaðu radíus leitarinnar. From 18224bef2d75f7b2856699e6320e9430b4f4b254 Mon Sep 17 00:00:00 2001 From: Gilbert Lowel Date: Fri, 30 Oct 2020 14:19:06 +0000 Subject: [PATCH 013/106] Translated using Weblate (Dutch) Currently translated at 96.4% (3397 of 3521 strings) --- OsmAnd/res/values-nl/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OsmAnd/res/values-nl/strings.xml b/OsmAnd/res/values-nl/strings.xml index 129ae33b02..3c40568702 100644 --- a/OsmAnd/res/values-nl/strings.xml +++ b/OsmAnd/res/values-nl/strings.xml @@ -3233,7 +3233,7 @@ \'Freeride\' en \'Off-piste\' zijn officieuze routes en passages. Meestal onverzorgd en niet onderhouden, en niet \'s avonds gecontroleerd. Betreden op eigen risico. Verzamelde data Laatste OsmAnd uitvoering gecrasht. Help ons alstublieft OsmAnd te verbeteren door de foutmelding te delen. - Persoonlijke transporteur + Persoonlijk transport Offroad WunderLINQ Wegtype @@ -3797,11 +3797,11 @@ \n" "• Profielen: nu kunt u de volgorde wijzigen, het pictogram voor de kaart instellen, alle instellingen voor basisprofielen wijzigen en ze terugzetten naar de standaardinstellingen \n -\n • Exitnummer toegevoegd in de navigatie +\n • Exitnummer toegevoegd in de navigatie \n -\n • Herwerkte plug-in instellingen +\n • Herwerkte plug-in instellingen \n -\n • Herwerkt instellingenscherm voor snelle toegang tot alle profielen +\n • Herwerkt instellingenscherm voor snelle toegang tot alle profielen \n \n • Optie toegevoegd om instellingen van een ander profiel te kopiëren \n From 0a6093e78d28b86b4c310f9f64e006019c97ec2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sveinn=20=C3=AD=20Felli?= Date: Fri, 30 Oct 2020 13:44:22 +0000 Subject: [PATCH 014/106] Translated using Weblate (Icelandic) Currently translated at 76.7% (208 of 271 strings) Translation: OsmAnd/Telegram Translate-URL: https://hosted.weblate.org/projects/osmand/telegram/is/ --- OsmAnd-telegram/res/values-is/strings.xml | 211 +++++++++++++++++++++- 1 file changed, 210 insertions(+), 1 deletion(-) diff --git a/OsmAnd-telegram/res/values-is/strings.xml b/OsmAnd-telegram/res/values-is/strings.xml index a6b3daec93..94bb15851c 100644 --- a/OsmAnd-telegram/res/values-is/strings.xml +++ b/OsmAnd-telegram/res/values-is/strings.xml @@ -1,2 +1,211 @@ - \ No newline at end of file + + Einingar og snið þeirra + Setja upp OsmAnd + Lykilorð + Meðalhæð + Fela + sendi (%1$d í biðminni) + Endursenda staðsetningu + Staðsetning… + Meðalhraði + Athugaðu og deildu nákvæmum atvikaskrám úr forritinu + Mílur/metrar + Lykilorð í Telegram + Deila staðsetningu sem + Deila staðsetningu + Sía: Stilltu lágmarksfjarlægð frá síðustu staðsetningu þar sem punktur er tekinn í skráningu + Til baka + Slökkt + Engin internettenging + Stilla tíma + Samþykkja + sek + %1$d mín + Mílur/fet + Vélmenni + Meðferð persónuupplýsinga í OsmAnd + Sendi staðsetningu + Tegund milliþjóns (proxy) + Breyta einingum sem notaðar eru við lengdarmælingar. + Staðsetningaferill + Merki OsmAnd + Gat ekki bætt við nýju tæki + Staða + Stillingar milliþjóns (proxy) + Gátt + Eftir nafni + Tímabelti + mín/km + m + Skráning staðsetningar virk + Tenging + Kílómetrar/metrar + Síðasta uppfærsla frá Telegram: Fyrir %1$s síðan + Vöktun er óvirk + Staða OsmAnd-rekjara + OsmAnd rekjari + Hópur + mín/ml + Netþjónn + Slökkva á öllu + Til baka í OsmAnd + Heiti tækis er of langt + Loka + %1$d klst %2$d mín + Mínútur á mílu + mín + Byrja + Vista + Landakort og texti + Lykilorð + %1$s bætt við. + Birta í OsmAnd + Síðasta tiltæka staðsetning + Sent + Auðkenningarkóði + Leita í tengiliðum + Opna OsmAnd + Endar + Settu inn auðkenningarkóða + Staðsetning mín + Skrá út + Birta á korti + Staða deilingar + Hætta við + Bíð eftir svari frá Telegram + Tókst að senda og uppfæra + Velja + Metrar á sekúndu + Heiti tækis + Velkomin + Hvernig það virkar + Stefna + Milliþjónn + Engin GPS-tenging + Senda staðsetningu sem + %1$d punktar + yd + Gera óvirkt + Tími á ferðinni + Sjómílur á klukkustund (hnútar) + %1$d klst + Lykill + Bakgrunnsvinna + Setja upp + Bæta við + Raða eftir + Síðasta svar: %1$s + Allt + Hæð + Birta GPS-punkta + Heiti tækis getur ekki verið tómt + Leita + Eftir vegalengd + Sjómílur + m/sek + Þú ert ekki skráð/ur inn + Ræsing + Lágmarksnákvæmni skráningar + Loka + Lágmarkshraði skráninga + OsmAnd rakningarþjónusta + Telegram + Kveikja á \"Staðsetning\"\? + Tengdur aðgangur + mi + Notandanafn + Heimild + Lengdareiningar + GPX-stillingar + Nýskráning í Telegram + Vegalengd + klst + km/klst + Skrá inn + Síðasta svar + Deila staðsetningu + ft + Nafn + %1$s síðan + Veldu notendur eða hópa til að deila með staðsetningu þinni. + Ég er ekki með Telegram-aðgang + Vöktun er virk + Rennur út + Gagnaleynd + Notandaaðgangur + Virkt + Nákvæmni + VILL + Ekki á ferð + Halda áfram + Staða + Upphafs — Endadagsetning + Aftengt + sml + Uppfæra + Settu inn lykilorð + Deila + Logcat biðminni + Settu inn símanúmer + Mínútur á kílómetra + Hætta + Útlit + Dagsetning + Síðar + Stefna + Hraðaeining + Landakort + Sía: Engin skráning punkta fyrir neðan þennan hraða + í %1$s + Leit: Hópur eða tengiliður + hnútar + km + Tímalína + Vistuð skilaboð + GPS-punktar + Virkja + Lágmarksfjarlægð skráninga + Síðasta uppfærsla frá Telegram + Safnað + Skrái út + Mílur/yardar + Veldu tíma sem á að birta + Auðkenni + Kílómetrar á klukkustund + Síðasta svar: Fyrir %1$s síðan + Tengist internetinu + Senda skýrslu + Flytja út + Mílur á klukkustund + Í lagi + Virkja + Persónuverndarstefna Telegram + Virkt spjall + Senda staðsetningu mína + Stungið upp á + Fara í stillingar + mi/klst + Deiling í bakgrunni + Deiling: %1$s + Síðasta uppfærsla frá Telegram: %1$s + Byrja + Raða + Engin gögn + Eftir hópi + Bæta við tæki + Texti + Stillingar + Birta notendur á kortinu + Tengt + Símanúmer + Upphafsdagsetning + Skilgreindu einingu fyrir hraða. + síðan + Settu inn kóða + Gera vöktun óvirka + Forritið hefur ekki heimildir til að nota staðsetningargögn. + Lokadagsetning + Bakgrunnshamur + OsmAnd-rakning keyrir í bakgrunni á meðan slökkt er á skjá. + \ No newline at end of file From ffb3f78ae15f5fa1d1abd6e5203dd759f6927998 Mon Sep 17 00:00:00 2001 From: Hakim Oubouali Date: Sat, 31 Oct 2020 10:09:05 +0100 Subject: [PATCH 015/106] Added translation using Weblate (Central Atlas Tamazight) --- OsmAnd/res/values-tzm/phrases.xml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 OsmAnd/res/values-tzm/phrases.xml diff --git a/OsmAnd/res/values-tzm/phrases.xml b/OsmAnd/res/values-tzm/phrases.xml new file mode 100644 index 0000000000..a6b3daec93 --- /dev/null +++ b/OsmAnd/res/values-tzm/phrases.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file From cd250108aeb36878291369ef521de5da9f3d19ac Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Sat, 31 Oct 2020 15:37:26 +0200 Subject: [PATCH 016/106] Refactoring --- .../backend/backup/FileSettingsItem.java | 2 +- .../backend/backup/SettingsHelper.java | 5 +- .../ExportImportSettingsAdapter.java | 6 +- .../fragments/ImportDuplicatesFragment.java | 64 ++++++++----------- .../fragments/ImportSettingsFragment.java | 51 +++++++-------- 5 files changed, 53 insertions(+), 75 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index bb66ad06d0..4ea7265310 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -45,7 +45,7 @@ public class FileSettingsItem extends StreamSettingsItem { } public boolean isMap() { - return this == OBF_MAP || this == WIKI_MAP || this == SRTM_MAP; + return this == OBF_MAP || this == WIKI_MAP || this == SRTM_MAP || this == TILES_MAP; } public boolean isDirectory() { 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 218d1a1f16..e912c670b4 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -684,10 +684,7 @@ public class SettingsHelper { multimediaFilesList.add(fileItem.getFile()); } else if (fileItem.getSubtype() == FileSubtype.GPX) { tracksFilesList.add(fileItem.getFile()); - } else if (fileItem.getSubtype() == FileSubtype.OBF_MAP - || fileItem.getSubtype() == FileSubtype.WIKI_MAP - || fileItem.getSubtype() == FileSubtype.SRTM_MAP - || fileItem.getSubtype() == FileSubtype.TILES_MAP) { + } else if (fileItem.getSubtype().isMap()) { mapFilesList.add(fileItem); } else if (fileItem.getSubtype() == FileSubtype.TTS_VOICE) { ttsVoiceFilesList.add(fileItem.getFile()); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java index e865b9a21b..94db277899 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java @@ -303,17 +303,13 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { subText.setVisibility(View.VISIBLE); break; case TTS_VOICE: - file = (File) currentItem; - title.setText(FileNameTranslationHelper.getFileName(app, - app.getResourceManager().getOsmandRegions(), - file.getName())); - setupIcon(icon, R.drawable.ic_action_volume_up, itemSelected); case VOICE: file = (File) currentItem; title.setText(FileNameTranslationHelper.getFileName(app, app.getResourceManager().getOsmandRegions(), file.getName())); setupIcon(icon, R.drawable.ic_action_volume_up, itemSelected); + break; default: return child; } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportDuplicatesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportDuplicatesFragment.java index cc23b78c9a..dc19f08eb2 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportDuplicatesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportDuplicatesFragment.java @@ -17,6 +17,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.widget.Toolbar; import androidx.core.view.ViewCompat; import androidx.core.widget.NestedScrollView; +import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -25,7 +26,6 @@ import com.google.android.material.appbar.CollapsingToolbarLayout; import net.osmand.AndroidUtils; import net.osmand.map.ITileSource; -import net.osmand.plus.AppInitializer; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; @@ -37,6 +37,7 @@ import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.backup.SettingsHelper; 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.SettingsHelper.SettingsImportListener; import net.osmand.plus.settings.backend.backup.SettingsItem; import net.osmand.view.ComplexButton; @@ -51,7 +52,7 @@ import static net.osmand.IndexConstants.ROUTING_PROFILES_DIR; import static net.osmand.plus.settings.fragments.ImportSettingsFragment.IMPORT_SETTINGS_TAG; -public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View.OnClickListener { +public class ImportDuplicatesFragment extends BaseOsmAndFragment { public static final String TAG = ImportDuplicatesFragment.class.getSimpleName(); private OsmandApplication app; @@ -68,8 +69,9 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View private SettingsHelper settingsHelper; public static void showInstance(@NonNull FragmentManager fm, List duplicatesList, - List settingsItems, File file) { + List settingsItems, File file, Fragment targetFragment) { ImportDuplicatesFragment fragment = new ImportDuplicatesFragment(); + fragment.setTargetFragment(targetFragment, 0); fragment.setDuplicatesList(duplicatesList); fragment.setSettingsItems(settingsItems); fragment.setFile(file); @@ -96,7 +98,11 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View if (file == null) { file = importTask.getFile(); } - importTask.setImportListener(getImportListener()); + Fragment target = getTargetFragment(); + if (target instanceof ImportSettingsFragment) { + SettingsImportListener importListener = ((ImportSettingsFragment) target).getImportListener(); + importTask.setImportListener(importListener); + } } } @@ -124,8 +130,18 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View ? getResources().getColor(R.color.active_buttons_and_links_text_dark) : getResources().getColor(R.color.active_buttons_and_links_text_light)) ); - keepBothBtn.setOnClickListener(this); - replaceAllBtn.setOnClickListener(this); + keepBothBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + importItems(false); + } + }); + replaceAllBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + importItems(true); + } + }); list = root.findViewById(R.id.list); ViewCompat.setNestedScrollingEnabled(list, false); ViewTreeObserver treeObserver = buttonsContainer.getViewTreeObserver(); @@ -242,20 +258,6 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View return duplicates; } - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.keep_both_btn: { - importItems(false); - break; - } - case R.id.replace_all_btn: { - importItems(true); - break; - } - } - } - @Override public int getStatusBarColorId() { return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light; @@ -267,7 +269,11 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View for (SettingsItem item : settingsItems) { item.setShouldReplace(shouldReplace); } - settingsHelper.importSettings(file, settingsItems, "", 1, getImportListener()); + Fragment target = getTargetFragment(); + if (target instanceof ImportSettingsFragment) { + SettingsImportListener importListener = ((ImportSettingsFragment) target).getImportListener(); + settingsHelper.importSettings(file, settingsItems, "", 1, importListener); + } } } @@ -282,22 +288,6 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View buttonsContainer.setVisibility(View.GONE); } - private SettingsHelper.SettingsImportListener getImportListener() { - return new SettingsHelper.SettingsImportListener() { - @Override - public void onSettingsImportFinished(boolean succeed, @NonNull List items) { - if (succeed) { - app.getRendererRegistry().updateExternalRenderers(); - AppInitializer.loadRoutingFiles(app, null); - FragmentManager fm = getFragmentManager(); - if (fm != null && file != null) { - ImportCompleteFragment.showInstance(fm, items, file.getName()); - } - } - } - }; - } - private void setupToolbar(Toolbar toolbar) { toolbar.setTitle(R.string.import_duplicates_title); toolbar.setNavigationIcon(getPaintedContentIcon( diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java index 8250477d20..2ecaad38e4 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java @@ -71,8 +71,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class ImportSettingsFragment extends BaseOsmAndFragment - implements View.OnClickListener { +public class ImportSettingsFragment extends BaseOsmAndFragment { public static final String TAG = ImportSettingsFragment.class.getSimpleName(); public static final Log LOG = PlatformUtil.getLog(ImportSettingsFragment.class.getSimpleName()); @@ -135,12 +134,28 @@ public class ImportSettingsFragment extends BaseOsmAndFragment progressBar = root.findViewById(R.id.progress_bar); setupToolbar(toolbar); ViewCompat.setNestedScrollingEnabled(expandableList, true); - View header = inflater.inflate(R.layout.list_item_description_header, null); + View header = inflater.inflate(R.layout.list_item_description_header, container, false); description = header.findViewById(R.id.description); description.setText(R.string.select_data_to_import); expandableList.addHeaderView(header); - continueBtn.setOnClickListener(this); - selectBtn.setOnClickListener(this); + continueBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (adapter.getData().isEmpty()) { + app.showShortToastMessage(getString(R.string.shared_string_nothing_selected)); + } else { + importItems(); + } + } + }); + selectBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + allSelected = !allSelected; + selectBtn.setText(allSelected ? R.string.shared_string_deselect_all : R.string.shared_string_select_all); + adapter.selectAll(allSelected); + } + }); if (Build.VERSION.SDK_INT >= 21) { AndroidUtils.addStatusBarPadding21v(app, root); } @@ -222,26 +237,6 @@ public class ImportSettingsFragment extends BaseOsmAndFragment } } - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.select_button: { - allSelected = !allSelected; - selectBtn.setText(allSelected ? R.string.shared_string_deselect_all : R.string.shared_string_select_all); - adapter.selectAll(allSelected); - break; - } - case R.id.continue_button: { - if (adapter.getData().isEmpty()) { - app.showShortToastMessage(getString(R.string.shared_string_nothing_selected)); - } else { - importItems(); - } - break; - } - } - } - private void updateUi(int toolbarTitleRes, int descriptionRes) { if (file != null) { String fileName = file.getName(); @@ -265,15 +260,15 @@ public class ImportSettingsFragment extends BaseOsmAndFragment } } - private SettingsHelper.SettingsImportListener getImportListener() { + public SettingsHelper.SettingsImportListener getImportListener() { return new SettingsHelper.SettingsImportListener() { @Override public void onSettingsImportFinished(boolean succeed, @NonNull List items) { - FragmentManager fm = getFragmentManager(); if (succeed) { app.getRendererRegistry().updateExternalRenderers(); AppInitializer.loadRoutingFiles(app, null); reloadIndexes(items); + FragmentManager fm = getFragmentManager(); if (fm != null && file != null) { ImportCompleteFragment.showInstance(fm, items, file.getName()); } @@ -348,7 +343,7 @@ public class ImportSettingsFragment extends BaseOsmAndFragment } settingsHelper.importSettings(file, items, "", 1, getImportListener()); } else if (fm != null && !isStateSaved()) { - ImportDuplicatesFragment.showInstance(fm, duplicates, items, file); + ImportDuplicatesFragment.showInstance(fm, duplicates, items, file, this); } } } From 2fd04c62314fe6d1870efd473a5206d37bfc861b Mon Sep 17 00:00:00 2001 From: Hardy Date: Sat, 31 Oct 2020 14:40:12 +0100 Subject: [PATCH 017/106] support de-casual in bundled assets --- OsmAnd/assets/bundled_assets.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/assets/bundled_assets.xml b/OsmAnd/assets/bundled_assets.xml index 30d1422d0f..9b69d7250c 100644 --- a/OsmAnd/assets/bundled_assets.xml +++ b/OsmAnd/assets/bundled_assets.xml @@ -12,6 +12,7 @@ + From f097cafd8cc7a203e736e218f581c648c6865ccc Mon Sep 17 00:00:00 2001 From: xmd5a Date: Sat, 31 Oct 2020 19:12:04 +0300 Subject: [PATCH 018/106] Add phrase --- OsmAnd/res/values/phrases.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OsmAnd/res/values/phrases.xml b/OsmAnd/res/values/phrases.xml index 04b193b923..0ca39e1de6 100644 --- a/OsmAnd/res/values/phrases.xml +++ b/OsmAnd/res/values/phrases.xml @@ -4265,4 +4265,6 @@ Sheds Layby + Radar tower + From efd0dd21d7ed25ecfd7679f14799960802cb58b8 Mon Sep 17 00:00:00 2001 From: ssantos Date: Sat, 31 Oct 2020 18:52:51 +0000 Subject: [PATCH 019/106] Translated using Weblate (Portuguese) Currently translated at 100.0% (3524 of 3524 strings) --- OsmAnd/res/values-pt/strings.xml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-pt/strings.xml b/OsmAnd/res/values-pt/strings.xml index 23fbc0cbcc..587dd8b707 100644 --- a/OsmAnd/res/values-pt/strings.xml +++ b/OsmAnd/res/values-pt/strings.xml @@ -3829,7 +3829,7 @@ Rota inversa O trilho inteiro será recalculado a usar o perfil selecionado. Somente o próximo segmento será recalculado a usar o perfil selecionado. - Selecione como ligar pontos, por uma linha reta ou a calcular uma rota entre eles como especificado abaixo. + Escolha como ligar os pontos por uma linha reta ou calcule uma rota entre eles como especificado abaixo. Trilho inteiro Próximo segmento Em seguida, encaixe a sua pista na estrada mais próxima permitida com um dos seus perfis de navegação para usar esta opção. @@ -3937,4 +3937,16 @@ \nO gráfico estará disponível após o recalculo. %1$s — %2$s Lacuna + MGRS + MGRS + O OsmAnd utiliza o MGRS, que é semelhante ao formato UTM NATO. + Mapas locais + Amenidade + Especial + Transporte + Serviço + Símbolos + Desporto + Emergência + Viagem \ No newline at end of file From 01f07f3c46b50e181c53f20dd0c14119b702de5f Mon Sep 17 00:00:00 2001 From: ffff23 Date: Sat, 31 Oct 2020 16:09:26 +0000 Subject: [PATCH 020/106] Translated using Weblate (Japanese) Currently translated at 97.7% (3446 of 3524 strings) --- OsmAnd/res/values-ja/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/res/values-ja/strings.xml b/OsmAnd/res/values-ja/strings.xml index c189909e5a..bbdfcef055 100644 --- a/OsmAnd/res/values-ja/strings.xml +++ b/OsmAnd/res/values-ja/strings.xml @@ -1808,7 +1808,7 @@ POIの更新は利用できません 項目の削除 項目は削除されました すべて元に戻す - タイプ + 種類 出発地点 指定しない レポート From 1babccd9abb203e2096aa34fba36eab31f43c67e Mon Sep 17 00:00:00 2001 From: Ldm Public Date: Sat, 31 Oct 2020 14:23:19 +0000 Subject: [PATCH 021/106] Translated using Weblate (French) Currently translated at 100.0% (3524 of 3524 strings) --- OsmAnd/res/values-fr/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml index 18fd7f8009..621bcc1627 100644 --- a/OsmAnd/res/values-fr/strings.xml +++ b/OsmAnd/res/values-fr/strings.xml @@ -3923,4 +3923,7 @@ Sport Urgence Voyage + OsmAnd utilise le système de référence MDRS de l\'OTAN dérivé des formats UTM et UPS. + MGRS + MGRS \ No newline at end of file From ac6efe84d5bd8da9898d50b974236958a0c5c576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20Ersen?= Date: Sat, 31 Oct 2020 10:29:28 +0000 Subject: [PATCH 022/106] Translated using Weblate (Turkish) Currently translated at 100.0% (3524 of 3524 strings) --- OsmAnd/res/values-tr/strings.xml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-tr/strings.xml b/OsmAnd/res/values-tr/strings.xml index 54debf38a3..3fd6a52de9 100644 --- a/OsmAnd/res/values-tr/strings.xml +++ b/OsmAnd/res/values-tr/strings.xml @@ -3783,7 +3783,7 @@ Ters güzergah Tüm yol, seçilen profil kullanılarak yeniden hesaplanacaktır. Sadece sonraki bölüm, seçilen profil kullanılarak yeniden hesaplanacaktır. - Düz bir çizgi ile noktaları nasıl birleştireceğinizi veya aşağıda belirtildiği gibi aralarında nasıl güzergah hesaplayacağınızı seçin. + Düz bir çizgi ile noktaların nasıl birleştirileceğini veya aşağıda belirtildiği gibi aralarında nasıl güzergah hesaplanacağını seçin. Tüm yol Sonraki bölüm Eşik mesafesi @@ -3888,4 +3888,18 @@ %1$s verileri yalnızca yollarda kullanılabilir, elde etmek için “Noktalar arasındaki güzergah” kullanarak bir rota hesaplamanız gerekir. Güzergahın yeniden hesaplanmasını bekleyin. \nGrafik yeniden hesaplandıktan sonra kullanılabilir olacak. + Boşluk + MGRS + MGRS + OsmAnd, UTM NATO biçimine benzer olan MGRS\'yi kullanmaktadır. + Yerel haritalar + %1$s — %2$s + Tesis + Özel + Ulaşım + Hizmet + Semboller + Spor + Acil + Seyahat \ No newline at end of file From 5c1ef6f1cb4f1cf9edcf0cfab52713ad09986039 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Sat, 31 Oct 2020 13:14:31 +0000 Subject: [PATCH 023/106] Translated using Weblate (Ukrainian) Currently translated at 100.0% (3524 of 3524 strings) --- OsmAnd/res/values-uk/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml index f75ae53dfc..1e88f7ad89 100644 --- a/OsmAnd/res/values-uk/strings.xml +++ b/OsmAnd/res/values-uk/strings.xml @@ -3940,4 +3940,7 @@ Спорт Аварійні служби Мандрівка + MGRS + MGRS + OsmAnd використовує MGRS, який подібний формату UTM NATO. \ No newline at end of file From 849d966fe744bdc004670793c622f2950abff0ba Mon Sep 17 00:00:00 2001 From: ace shadow Date: Sat, 31 Oct 2020 22:10:34 +0000 Subject: [PATCH 024/106] Translated using Weblate (Slovak) Currently translated at 100.0% (3524 of 3524 strings) --- OsmAnd/res/values-sk/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-sk/strings.xml b/OsmAnd/res/values-sk/strings.xml index 1ae947c024..4ff057ec8f 100644 --- a/OsmAnd/res/values-sk/strings.xml +++ b/OsmAnd/res/values-sk/strings.xml @@ -3944,4 +3944,7 @@ Šport Núdzová situácia/Záchrana Cestovanie + MGRS + MGRS + OsmAnd používa MGSR, ktorý je podobný ako formát UTM NATO. \ No newline at end of file From 3fb7f50c40cb6ebfe12dc128839e3e52b482a88c Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Sat, 31 Oct 2020 15:25:15 +0000 Subject: [PATCH 025/106] Translated using Weblate (Hebrew) Currently translated at 99.9% (3523 of 3524 strings) --- OsmAnd/res/values-iw/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-iw/strings.xml b/OsmAnd/res/values-iw/strings.xml index c82e5e3b8d..b27a8291d6 100644 --- a/OsmAnd/res/values-iw/strings.xml +++ b/OsmAnd/res/values-iw/strings.xml @@ -3948,4 +3948,7 @@ ספורט חירום טיול + ב־OsmAnd נעשה שימוש ב־MGRS, שדומה לתצורת UTM NATO. + MGRS + MGRS \ No newline at end of file From 68f64466f58425a624ffbf18faeb7d5cc9ae2cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1ns?= Date: Sat, 31 Oct 2020 14:13:33 +0000 Subject: [PATCH 026/106] Translated using Weblate (Galician) Currently translated at 100.0% (3524 of 3524 strings) --- OsmAnd/res/values-gl/strings.xml | 96 +++++++++++++++++++------------- 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/OsmAnd/res/values-gl/strings.xml b/OsmAnd/res/values-gl/strings.xml index 447bdc7bbf..e422eecf62 100644 --- a/OsmAnd/res/values-gl/strings.xml +++ b/OsmAnd/res/values-gl/strings.xml @@ -500,15 +500,15 @@ Deter a música Mapas e navegación OsmAnd Visualización e navegación móbil de mapas globais do OSM con e sen conexión - OsmAnd (Indicacións de navegación automatizadas do OSM) -\n + OsmAnd (Indicacións de navegación automatizadas do OSM) +\n \n O OsmAnd é unha aplicación de navegación de código aberto con acceso a unha ampla variedade de datos globais do OSM. Tódolos datos do mapa (mapas vectoriais ou teselas) poden ser almacenados no cartón de memoria do teléfono móbil para empregalos sen conexión. O OsmAnd tamen fornece a funcionalidade de cálculo de rotas sen conexión, incluíndo a guía por voz paso a paso. \n \n Algunhas das funcións principais: \n - Funcionalidade completa sen conexión (os mapas vectoriais ou de teselas baixados almacénanse no cartafol que se escolla) \n - Mapas vectoriais compactos sen conexión para todo o mundo \n - Pódense baixar mapas de países ou rexións de xeito directo dende a aplicación -\n - É posíbel sobrepor varias capas de mapas, coma pistas de GPX ou de navegación, puntos de interese (PDI), favoritos, curvas do nivel, paraxes de transporte público ou mapas adicionais con transparencia regulábel +\n - É posíbel sobrepor varias capas de mapas, coma pistas de GPX ou de navegación, puntos de interese (PDI), favoritos, curvas do nivel, paradas de transporte público ou mapas adicionais con transparencia regulábel \n - Procura sen conexión dos enderezos e lugares (PDI) \n - Cálculo de rotas sen conexión para distancias medias \n - Modos para automóbil, bicicleta e peóns, opcionalmente con: @@ -517,29 +517,29 @@ \n - Aliñamento do mapa dependendo do compás ou da dirección do movemento \n - Guía de faixas ou carrís da estrada, límites de velocidade, voces gravadas e TTS \n -\n Limitacións desta versión de balde do OsmAnd: -\n - O número de mapas a baixar está limitado -\n - Non hai acceso ós puntos de interese (PDI) da Wikipedia sen conexión -\n +\n Limitacións desta versión de balde do OsmAnd: +\n - O número de mapas a baixar está limitado +\n - Non hai acceso ós puntos de interese (PDI) da Wikipedia sen conexión +\n \n O OsmAnd está a ser desenvolvido activamente e o noso proxecto e o seu progreso futuro depende da contribución financeira para financia-lo desenvolvemento e as probas das funcionalidades novas. Coida a posibilidade de mercar o OsmAnd+ ou de financiar funcións novas específicas ou de facer unha doazón xeral no osmand.net. Mapas e navegación de OsmAnd+ Visualización e navegación móbil de mapas globais para mapas de OSM con e sen conexión - O OsmAnd+ (Indicacións da navegación automatizadas do OSM) é un aplicativo de navegación de código aberto con acceso a unha ampla variedade de datos globais do OSM. Tódolos mapas dos datos (mapas vectoriais ou teselas) poden seren almacenados no cartón de memoria do teléfono para empregalos sen conexión. O OsmAnd tamén fornece funcionalidade de cálculo de rotas sen conexión, incluíndo a guía por voz paso a paso. -\n -\nO OsmAnd+ é a versión de pagamento, mais ó mercala estás a apoiar o proxecto, financiar o desenvolvemento de funcións novas e tes a oportunidade de recibir as últimas actualizacións. -\n -\nAlgunhas das funcións principais son: -\n-Funcionalidade completa sen conexión (os mapas vectoriais ou de teselas baixados almacénanse no cartafol que se escolleu) -\n-Mapas vectoriais compactos sen conexión para todo o mundo. -\n-Pódense baixar mapas de países ou rexións de xeito directo dende a aplicación. -\n-É posíbel sobrepór varias capas de mapas, coma pistas de GPX ou de navegación, puntos de interese (PDI), favoritos, curvas do nivel, paraxes de transporte público ou mapas adicionais con transparencia regulábel. -\n -\n- Procura sen conexión de enderezos e lugares (PDI). -\n-Cálculo de rotas sen conexión para distancias curtas (distancias medias) -\n- Modos para automóbil, bicicleta e peóns, con: -\n-Vistas de noite e día automatizadas opcionais. -\n-Achegamento opcional do mapa dependendo da velocidade -\n-Aliñamento opcional do mapa dependendo do compás ou da dirección do movemento. + O OsmAnd+ (Indicacións da navegación automatizadas do OSM) é un aplicativo de navegación de código aberto con acceso a unha ampla variedade de datos globais do OSM. Tódolos mapas dos datos (mapas vectoriais ou teselas) poden seren almacenados no cartón de memoria do teléfono para empregalos sen conexión. O OsmAnd tamén fornece funcionalidade de cálculo de rotas sen conexión, incluíndo a guía por voz paso a paso. +\n +\nO OsmAnd+ é a versión de pagamento, mais ó mercala estás a apoiar o proxecto, financiar o desenvolvemento de funcións novas e tes a oportunidade de recibir as últimas actualizacións. +\n +\nAlgunhas das funcións principais son: +\n-Funcionalidade completa sen conexión (os mapas vectoriais ou de teselas baixados almacénanse no cartafol que se escolleu) +\n-Mapas vectoriais compactos sen conexión para todo o mundo. +\n-Pódense baixar mapas de países ou rexións de xeito directo dende a aplicación. +\n-É posíbel sobrepór varias capas de mapas, coma pistas de GPX ou de navegación, puntos de interese (PDI), favoritos, curvas do nivel, paradas de transporte público ou mapas adicionais con transparencia regulábel. +\n +\n- Procura sen conexión de enderezos e lugares (PDI). +\n-Cálculo de rotas sen conexión para distancias curtas (distancias medias) +\n- Modos para automóbil, bicicleta e peóns, con: +\n-Vistas de noite e día automatizadas opcionais. +\n-Achegamento opcional do mapa dependendo da velocidade +\n-Aliñamento opcional do mapa dependendo do compás ou da dirección do movemento. \n-Guía opcional de faixas ou carrís da estrada, límites de velocidade, voces gravadas e TTS \n Crear un filtro de PDI @@ -1043,7 +1043,7 @@ Non foi posíbel atopar ficheiros GPX no cartafol de pistas Non foi posíbel ler os datos do GPX. Mapas vectoriais sen conexión - Procurar transporte na paraxe + Procurar transporte na parada Modificar o PDI Eliminar PDI Dirección do compás @@ -1126,19 +1126,19 @@ Engadir unha regra nova Liñas Stop - paraxes + paradas Itinerario posterior Itinerario anterior Rematar a procura - Escolle a paraxe na que baixar + Escolle a parada na que baixar distancia anterior distancia posterior - paraxes a pasar + paradas a pasar Distancia do itinerario Transporte Feito - Amosar paraxes do transporte público no mapa. - Amosar paraxes do transporte + Amosar paradas de transporte público no mapa. + Amosar paradas de transporte OsmAnd, aplicación de navegación Os datos do PDI foron actualizados ({0} foron carregados) Non podes atualizar a listaxe local de PDI. @@ -1986,7 +1986,7 @@ Lon %2$s Empregar o camiño con aforro no combustíbel (normalmente máis curto). Mudar Comezar - %1$s paraxes antes + %1$s paradas antes Inserir o enderezo do destino mediante vibración. Activar a navegación por modificacións do OsmAnd ao Vivo. Non recalcular a ruta ó saírme da mesma @@ -2362,8 +2362,8 @@ Lon %2$s Mapa importado Converter isto no punto de partida Actual - Engade unha paraxe intermedia - Engade a primeira paraxe do percorrido + Engade unha parada intermedia + Engade a primeira parada do percorrido Move o destino cara enriba e crea un novo Amosar/agochar as notas do OSM no mapa. GPX - axeitado para exportar a JOSM ou outros editores do OSM. @@ -2430,7 +2430,7 @@ Lon %2$s Primeiro especificar a cidade, vila ou lugar Restaurar Manter no mapa as marcaxes desbotadas - Máis transportes dispoñíbeis dende esta paraxe. + Máis transportes dispoñíbeis dende esta parada. Para proseguer, permite acceder á localización ó OsmAnd. Grazas polos teus comentarios Non foi posíbel atopar o nó ou a vía. @@ -2757,11 +2757,11 @@ Lon %2$s \n• Olla a velocidade e altitude \n• A opción da gravación GPX, permite gravar o viaxe e partillalo ou compartilo \n• Mediante un plugin adicional, podes activar as curvas de nivel e o asombreado dos outeiros ou colinas - Camiñar, sendeirismo, turismo de cidade -\n • O mapa amosa as rotas para camiñar e de sendeirismo -\n • Wikipedia na lingua de preferencia, pode dicir moito durante unha visita turística -\n • As paraxes do transporte público (autobús, tranvía, tren), incluíndo os nomes de liña, axuda a navigar nunha nova cidade -\n • Navegación GPS no modo peón, constrúe a rota empregando rotas de sendeirismo + Camiñar, sendeirismo, turismo de cidade +\n • O mapa amosa as rotas para camiñar e de sendeirismo +\n • Wikipedia na lingua de preferencia, pode dicir moito durante unha visita turística +\n • As paradas do transporte público (autobús, tranvía, tren), incluíndo os nomes de liña, axuda a navigar nunha nova cidade +\n • Navegación GPS no modo peón, constrúe a rota empregando rotas de sendeirismo \n • Soba e sigua unha rota GPX ou grave e partille ou comparta as súas propias rotas \n Contribúe co OSM @@ -2897,7 +2897,7 @@ Lon %2$s Tódolos cruzamentos (xiro a xiro) Tipos de estrada Saír en - Embarcar na paraxe + Embarcar na parada Trocar Amosar máis Pistas amosadas @@ -3879,7 +3879,7 @@ Lon %2$s Ruta inversa Recalcular toda a pista empregando o perfil escollido. Recalcular só o seguinte segmento empregando o perfil escollido. - Marca de que xeito conectar os puntos, cunha liña recta ou calcular unha ruta entre eles como se detalla deseguido. + Escolle de que xeito conectar os puntos, cunha liña recta ou calcular unha ruta entre eles como se detalla deseguido. Pista enteira Seguinte segmento Deseguido, axusta a pista á estrada permitida máis preto cun perfil de navegación. @@ -3955,4 +3955,20 @@ Lon %2$s Usar algoritmo de enrutamento A* de 2 fases Gráfica %1$s — %2$s + MGRS + MGRS + O OsmAnd emprega MGRS, que é semellante ó formato UTM NATO. + %1$s datos dispoñíbeis só nas estrada, necesitas calcular unha ruta empregando \"Ruta entre puntos\" para obtela. + Agarda polo recálculo da ruta. +\nO gráfico estará dispoñíbel após o recálculo. + Mapas locais + Salto + Instalación + Especial + Transporte + Servizo + Símbolos + Deporte + Emerxencia + Viaxe \ No newline at end of file From 4c1fba659a18070888f3602b489419e63324d567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1ns?= Date: Sat, 31 Oct 2020 14:17:52 +0000 Subject: [PATCH 027/106] Translated using Weblate (Galician) Currently translated at 100.0% (3829 of 3829 strings) --- OsmAnd/res/values-gl/phrases.xml | 40 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/OsmAnd/res/values-gl/phrases.xml b/OsmAnd/res/values-gl/phrases.xml index b974255f35..b377d6ec35 100644 --- a/OsmAnd/res/values-gl/phrases.xml +++ b/OsmAnd/res/values-gl/phrases.xml @@ -72,14 +72,14 @@ Aparcadoiro de motos Entrada de aparcadoiro Garaxes - Paraxe de transporte público - Paraxe de bus - Paraxe de trolebus - Paraxe do tranvía + Parada de transporte público + Parada de bus + Parada de trolebus + Parada de tranvía Estación de transporte público Entrada de metro Si - Paraxe de taxis + Parada de taxis Aeroporto Heliporto Faro @@ -428,8 +428,8 @@ Metanol Hidróxeno líquido Electricidade - Paraxe de bus - Paraxe do tranvía + Parada de bus + Parada de tranvía Estación de autobuses Estación de trens Terminal dos ferris @@ -1352,7 +1352,7 @@ OV-Chipkaart Cafetaría Tipo - Punto de paraxe do transporte público + Lugar de parada de transporte público Vértice xeodésico Instalación social Asesoramento fiscal @@ -1403,7 +1403,7 @@ Tipo de glaciar Tipo de posto de control Tenda de ultramarinos - Paraxe de trens + Parada de tren Fin da vía Estabelecemento de comidas Boia de instalación @@ -3554,18 +3554,18 @@ Categoría da dificultade Radioterapia Perigo - н/к - н/к* - - 1А* + n/c + n/c* + 1A + 1A* 1B 1B* - - 2А* + 2A + 2A* 2B 2B* - - 3А* + 3A + 3A* 3B 3B* Chama de gas;Queimadura de facho @@ -3793,7 +3793,7 @@ Tipo de cabina Si Non - Sinal para atopar o poste + Acceso á internet: clientes Só é permitido ó camiñar Contrastado Primitivo @@ -3838,4 +3838,8 @@ Taboleiro de saídas Recarga de auga potábel GNL + Apartadoiro + Pendellos + Terrazo + Punto GPX \ No newline at end of file From 6de7936ba153e2db3248ae9cda754a47793de975 Mon Sep 17 00:00:00 2001 From: Eduardo Addad de Oliveira Date: Sat, 31 Oct 2020 21:14:52 +0000 Subject: [PATCH 028/106] Translated using Weblate (Portuguese (Brazil)) Currently translated at 99.9% (3523 of 3524 strings) --- OsmAnd/res/values-pt-rBR/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml index 0d88da8148..8d0920e8af 100644 --- a/OsmAnd/res/values-pt-rBR/strings.xml +++ b/OsmAnd/res/values-pt-rBR/strings.xml @@ -3938,4 +3938,7 @@ Esporte Emergência Viagem + MGRS + MGRS + OsmAnd usa MGRS, que é semelhante ao formato UTM NATO. \ No newline at end of file From 5badce01e39de20cba0e5c48e08b1f7f02f2ca4d Mon Sep 17 00:00:00 2001 From: ssantos Date: Sat, 31 Oct 2020 18:56:02 +0000 Subject: [PATCH 029/106] Translated using Weblate (Portuguese) Currently translated at 99.9% (3828 of 3829 strings) --- OsmAnd/res/values-pt/phrases.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-pt/phrases.xml b/OsmAnd/res/values-pt/phrases.xml index 05bf64827a..978eb601ae 100644 --- a/OsmAnd/res/values-pt/phrases.xml +++ b/OsmAnd/res/values-pt/phrases.xml @@ -3786,7 +3786,7 @@ Primitivo Contrastado Somente quando é permitido caminhar - Sinal para encontrar o poste + Acesso à Internet: clientes Não Sim Tipo de cabine @@ -3830,4 +3830,7 @@ Colmeia Loja de nozes GNL + Barracão + Telhado + Ponto GPX \ No newline at end of file From 3b31fc98d97fcfb5cf5def509bcd37d175c85736 Mon Sep 17 00:00:00 2001 From: Hakim Oubouali Date: Sat, 31 Oct 2020 21:31:16 +0000 Subject: [PATCH 030/106] Translated using Weblate (Central Atlas Tamazight) Currently translated at 0.1% (3 of 3524 strings) --- OsmAnd/res/values-tzm/strings.xml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-tzm/strings.xml b/OsmAnd/res/values-tzm/strings.xml index a6b3daec93..1ae1b1ba84 100644 --- a/OsmAnd/res/values-tzm/strings.xml +++ b/OsmAnd/res/values-tzm/strings.xml @@ -1,2 +1,22 @@ - \ No newline at end of file + + Takaṛḍa tadɣarant + %1$s — %2$s + Tanafut + + + + + + + + + + + + + + + + + \ No newline at end of file From 1b153f8c15ab0062b0eeda5a7e42a90fb90b34e5 Mon Sep 17 00:00:00 2001 From: Hakim Oubouali Date: Sat, 31 Oct 2020 09:22:04 +0000 Subject: [PATCH 031/106] Translated using Weblate (Central Atlas Tamazight) Currently translated at 18.0% (49 of 271 strings) Translation: OsmAnd/Telegram Translate-URL: https://hosted.weblate.org/projects/osmand/telegram/tzm/ --- OsmAnd-telegram/res/values-tzm/strings.xml | 52 +++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/OsmAnd-telegram/res/values-tzm/strings.xml b/OsmAnd-telegram/res/values-tzm/strings.xml index a6b3daec93..e2a8f81966 100644 --- a/OsmAnd-telegram/res/values-tzm/strings.xml +++ b/OsmAnd-telegram/res/values-tzm/strings.xml @@ -1,2 +1,52 @@ - \ No newline at end of file + + Aɣul + Bḍu + Ssekcem uṭṭun n utilifun + Akk + Abut + Usrid + g %1$s + Amiḍan + Rgel + Tarabbut + aya + Ffeɣ + Fren s + Fren + S trabbut + S isem + Isem + Bḍu adɣar am + Rnu allal + Ḥḍu + Addad + Ddu ɣer tesɣal + Azan n udɣar + Ssentel + Rnu + Taleqqemt tameggarut seg Tiligṛam + Takaṛḍa d uḍṛiṣ + Aḍṛiṣ + Takaṛḍa + Azen adɣar am + Asakud n usenti + Asakud + Ssedɣi + Tiligṛam + WAX + Rzu + Tanila + Tinnutla + Apṛuksi + Tisɣal n Upṛuksi + Izdey + Anaw n upṛuksi + Taguri n uzray + Tasarut + Tisɣal n GPX + Stey + Ssenti + Aɣul ɣer OsmAnd + %1$s aya + \ No newline at end of file From 4e80496d1e7046d0886e57954994069ba0c3475f Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Sun, 1 Nov 2020 16:42:54 +0200 Subject: [PATCH 032/106] remove unnecessary import --- OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java | 1 - 1 file changed, 1 deletion(-) diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java index 3ae28d83b2..36c8e797f1 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java @@ -36,7 +36,6 @@ import net.osmand.plus.measurementtool.graph.BaseGraphAdapter; import net.osmand.plus.measurementtool.graph.GraphAdapterHelper; import net.osmand.plus.routepreparationmenu.RouteDetailsFragment; import net.osmand.plus.routepreparationmenu.cards.BaseCard; -import net.osmand.plus.routepreparationmenu.cards.RouteStatisticCard; import net.osmand.router.RouteSegmentResult; import net.osmand.util.Algorithms; From c606260def14cfc3de4017727d31509e64f73618 Mon Sep 17 00:00:00 2001 From: androiddevkkotlin Date: Sun, 1 Nov 2020 17:38:09 +0200 Subject: [PATCH 033/106] Add favorite custom colors --- OsmAnd/res/layout/colors_card.xml | 17 ++ .../res/layout/point_editor_fragment_new.xml | 6 + .../editors/PointEditorFragmentNew.java | 62 +++-- .../cards/RouteInfoCard.java | 4 +- .../src/net/osmand/plus/track/ColorsCard.java | 243 ++++++++++++++++++ 5 files changed, 303 insertions(+), 29 deletions(-) create mode 100644 OsmAnd/res/layout/colors_card.xml create mode 100644 OsmAnd/src/net/osmand/plus/track/ColorsCard.java diff --git a/OsmAnd/res/layout/colors_card.xml b/OsmAnd/res/layout/colors_card.xml new file mode 100644 index 0000000000..bef11dc500 --- /dev/null +++ b/OsmAnd/res/layout/colors_card.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/point_editor_fragment_new.xml b/OsmAnd/res/layout/point_editor_fragment_new.xml index 21c6396c53..36e46a6cab 100644 --- a/OsmAnd/res/layout/point_editor_fragment_new.xml +++ b/OsmAnd/res/layout/point_editor_fragment_new.xml @@ -458,6 +458,12 @@ android:layout_height="1dp" android:background="?attr/dashboard_divider" /> + + customColors; + + private int selectedColor; + + @Override + public int getCardLayoutId() { + return R.layout.colors_card; + } + + public ColorsCard(MapActivity mapActivity, int selectedColor, Fragment targetFragment, int[] colors) { + super(mapActivity); + this.targetFragment = targetFragment; + this.selectedColor = selectedColor; + this.colors = colors; + customColors = getCustomColors(); + } + + public int getSelectedColor() { + return selectedColor; + } + + public void setSelectedColor(int selectedColor) { + this.selectedColor = selectedColor; + } + + @Override + public void onColorSelected(Integer prevColor, int newColor) { + if (prevColor != null) { + int index = customColors.indexOf(prevColor); + if (index != INVALID_VALUE) { + customColors.set(index, newColor); + } + if (selectedColor == prevColor) { + selectedColor = newColor; + } + } else if (customColors.size() < MAX_CUSTOM_COLORS) { + customColors.add(newColor); + selectedColor = newColor; + } + saveCustomColors(); + updateContent(); + } + + @Override + protected void updateContent() { + createColorSelector(); + updateColorSelector(selectedColor, view); + } + + private void createColorSelector() { + FlowLayout selectColor = view.findViewById(R.id.select_color); + selectColor.removeAllViews(); + + for (int color : customColors) { + selectColor.addView(createColorItemView(color, selectColor, true)); + } + if (customColors.size() < 6) { + selectColor.addView(createAddCustomColorItemView(selectColor)); + } + selectColor.addView(createDividerView(selectColor)); + + for (int color : colors) { + selectColor.addView(createColorItemView(color, selectColor, false)); + } + updateColorSelector(selectedColor, selectColor); + } + + private void updateColorSelector(int color, View rootView) { + View oldColor = rootView.findViewWithTag(selectedColor); + if (oldColor != null) { + oldColor.findViewById(R.id.outline).setVisibility(View.INVISIBLE); + ImageView icon = oldColor.findViewById(R.id.icon); + icon.setImageDrawable(UiUtilities.tintDrawable(icon.getDrawable(), R.color.icon_color_default_light)); + } + View newColor = rootView.findViewWithTag(color); + if (newColor != null) { + newColor.findViewById(R.id.outline).setVisibility(View.VISIBLE); + } + } + + private View createColorItemView(@ColorInt final int color, final FlowLayout rootView, boolean customColor) { + View colorItemView = createCircleView(rootView); + + ImageView backgroundCircle = colorItemView.findViewById(R.id.background); + + Drawable transparencyIcon = getTransparencyIcon(app, color); + Drawable colorIcon = app.getUIUtilities().getPaintedIcon(R.drawable.bg_point_circle, color); + Drawable layeredIcon = UiUtilities.getLayeredIcon(transparencyIcon, colorIcon); + double contrastRatio = ColorUtils.calculateContrast(color, ContextCompat.getColor(app, nightMode ? R.color.card_and_list_background_dark : R.color.card_and_list_background_light)); + if (contrastRatio < MINIMUM_CONTRAST_RATIO) { + backgroundCircle.setBackgroundResource(nightMode ? R.drawable.circle_contour_bg_dark : R.drawable.circle_contour_bg_light); + } + backgroundCircle.setImageDrawable(layeredIcon); + backgroundCircle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateColorSelector(color, rootView); + selectedColor = color; + + CardListener listener = getListener(); + if (listener != null) { + listener.onCardPressed(ColorsCard.this); + } + } + }); + if (customColor) { + backgroundCircle.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + CustomColorBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), targetFragment, color); + } + return false; + } + }); + } + colorItemView.setTag(color); + return colorItemView; + } + + private View createAddCustomColorItemView(FlowLayout rootView) { + View colorItemView = createCircleView(rootView); + ImageView backgroundCircle = colorItemView.findViewById(R.id.background); + + int bgColorId = nightMode ? R.color.activity_background_color_dark : R.color.activity_background_color_light; + Drawable backgroundIcon = app.getUIUtilities().getIcon(R.drawable.bg_point_circle, bgColorId); + + ImageView icon = colorItemView.findViewById(R.id.icon); + icon.setVisibility(View.VISIBLE); + int activeColorResId = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; + icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_plus, activeColorResId)); + + backgroundCircle.setImageDrawable(backgroundIcon); + backgroundCircle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + CustomColorBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), targetFragment, null); + } + } + }); + return colorItemView; + } + + private View createDividerView(FlowLayout rootView) { + LayoutInflater themedInflater = UiUtilities.getInflater(view.getContext(), nightMode); + View divider = themedInflater.inflate(R.layout.simple_divider_item, rootView, false); + + LinearLayout dividerContainer = new LinearLayout(view.getContext()); + dividerContainer.addView(divider); + dividerContainer.setPadding(0, AndroidUtils.dpToPx(app, 1), 0, AndroidUtils.dpToPx(app, 5)); + + return dividerContainer; + } + + private View createCircleView(ViewGroup rootView) { + LayoutInflater themedInflater = UiUtilities.getInflater(view.getContext(), nightMode); + View circleView = themedInflater.inflate(R.layout.point_editor_button, rootView, false); + ImageView outline = circleView.findViewById(R.id.outline); + int colorId = nightMode ? R.color.stroked_buttons_and_links_outline_dark : R.color.stroked_buttons_and_links_outline_light; + Drawable contourIcon = app.getUIUtilities().getIcon(R.drawable.bg_point_circle_contour, colorId); + outline.setImageDrawable(contourIcon); + return circleView; + } + + private Drawable getTransparencyIcon(OsmandApplication app, @ColorInt int color) { + int colorWithoutAlpha = UiUtilities.removeAlpha(color); + int transparencyColor = UiUtilities.getColorWithAlpha(colorWithoutAlpha, 0.8f); + return app.getUIUtilities().getPaintedIcon(R.drawable.ic_bg_transparency, transparencyColor); + } + + private List getCustomColors() { + List colors = new ArrayList<>(); + List colorNames = app.getSettings().CUSTOM_TRACK_COLORS.getStringsList(); + if (colorNames != null) { + for (String colorHex : colorNames) { + try { + if (!Algorithms.isEmpty(colorHex)) { + int color = Algorithms.parseColor(colorHex); + colors.add(color); + } + } catch (IllegalArgumentException e) { + log.error(e); + } + } + } + return colors; + } + + private void saveCustomColors() { + List colorNames = new ArrayList<>(); + for (Integer color : customColors) { + String colorHex = Algorithms.colorToString(color); + colorNames.add(colorHex); + } + app.getSettings().CUSTOM_TRACK_COLORS.setStringsList(colorNames); + } +} \ No newline at end of file From 48f81f2ccc0d5e62e01874c12ffb347ac22346f7 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Mon, 2 Nov 2020 03:36:07 +0200 Subject: [PATCH 034/106] Minor fixes --- .../res/layout/point_editor_fragment_new.xml | 10 +---- .../editors/PointEditorFragmentNew.java | 43 +++++++++---------- .../src/net/osmand/plus/track/ColorsCard.java | 4 +- 3 files changed, 25 insertions(+), 32 deletions(-) diff --git a/OsmAnd/res/layout/point_editor_fragment_new.xml b/OsmAnd/res/layout/point_editor_fragment_new.xml index 36e46a6cab..9be9841750 100644 --- a/OsmAnd/res/layout/point_editor_fragment_new.xml +++ b/OsmAnd/res/layout/point_editor_fragment_new.xml @@ -444,9 +444,9 @@ osmand:typeface="@string/font_roboto_medium" /> - - - colors = new ArrayList<>(); + for (int color : ColorDialogs.pallette) { + colors.add(color); + } + int customColor = getPointColor(); + if (!ColorDialogs.isPaletteColor(customColor)) { + colors.add(customColor); + } + colorsCard = new ColorsCard(mapActivity, selectedColor, this, colors); + colorsCard.setListener(this); + LinearLayout selectColor = view.findViewById(R.id.select_color); + selectColor.addView(colorsCard.build(view.getContext())); + } } @Override public void onColorSelected(Integer prevColor, int newColor) { - trackColoringCard.onColorSelected(prevColor, newColor); - selectedColor = trackColoringCard.getSelectedColor(); - updateColorSelector(selectedColor, view); + colorsCard.onColorSelected(prevColor, newColor); + int color = colorsCard.getSelectedColor(); + updateColorSelector(color, view); } - ColorsCard trackColoringCard; - @Override public void onCardLayoutNeeded(@NonNull BaseCard card) { @@ -487,8 +496,8 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment implemen @Override public void onCardPressed(@NonNull BaseCard card) { if (card instanceof ColorsCard) { - selectedColor = ((ColorsCard) card).getSelectedColor(); - updateColorSelector(selectedColor, view); + int color = ((ColorsCard) card).getSelectedColor(); + updateColorSelector(color, view); } } @@ -498,16 +507,6 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment implemen } private void updateColorSelector(int color, View rootView) { - View oldColor = rootView.findViewWithTag(selectedColor); - if (oldColor != null) { - oldColor.findViewById(R.id.outline).setVisibility(View.INVISIBLE); - ImageView icon = oldColor.findViewById(R.id.icon); - icon.setImageDrawable(UiUtilities.tintDrawable(icon.getDrawable(), R.color.icon_color_default_light)); - } - View newColor = rootView.findViewWithTag(color); - if (newColor != null) { - newColor.findViewById(R.id.outline).setVisibility(View.VISIBLE); - } ((TextView) view.findViewById(R.id.color_name)).setText(ColorDialogs.getColorName(color)); selectedColor = color; setColor(color); diff --git a/OsmAnd/src/net/osmand/plus/track/ColorsCard.java b/OsmAnd/src/net/osmand/plus/track/ColorsCard.java index 596755c1f8..cb3c12936e 100644 --- a/OsmAnd/src/net/osmand/plus/track/ColorsCard.java +++ b/OsmAnd/src/net/osmand/plus/track/ColorsCard.java @@ -40,7 +40,7 @@ public class ColorsCard extends BaseCard implements ColorPickerListener { private Fragment targetFragment; - private int[] colors; + private List colors; private List customColors; private int selectedColor; @@ -50,7 +50,7 @@ public class ColorsCard extends BaseCard implements ColorPickerListener { return R.layout.colors_card; } - public ColorsCard(MapActivity mapActivity, int selectedColor, Fragment targetFragment, int[] colors) { + public ColorsCard(MapActivity mapActivity, int selectedColor, Fragment targetFragment, List colors) { super(mapActivity); this.targetFragment = targetFragment; this.selectedColor = selectedColor; From 3a3ea4825b3598fea4984c7ab609927d1f6731c6 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Mon, 2 Nov 2020 04:12:11 +0200 Subject: [PATCH 035/106] Remove code duplicates in custom colors --- .../src/net/osmand/plus/track/ColorsCard.java | 5 +- .../plus/track/TrackAppearanceFragment.java | 60 ++++- .../osmand/plus/track/TrackColoringCard.java | 217 +----------------- 3 files changed, 62 insertions(+), 220 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/track/ColorsCard.java b/OsmAnd/src/net/osmand/plus/track/ColorsCard.java index cb3c12936e..9fee9408c4 100644 --- a/OsmAnd/src/net/osmand/plus/track/ColorsCard.java +++ b/OsmAnd/src/net/osmand/plus/track/ColorsCard.java @@ -8,6 +8,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.fragment.app.Fragment; @@ -55,7 +56,7 @@ public class ColorsCard extends BaseCard implements ColorPickerListener { this.targetFragment = targetFragment; this.selectedColor = selectedColor; this.colors = colors; - customColors = getCustomColors(); + customColors = getCustomColors(app); } public int getSelectedColor() { @@ -214,7 +215,7 @@ public class ColorsCard extends BaseCard implements ColorPickerListener { return app.getUIUtilities().getPaintedIcon(R.drawable.ic_bg_transparency, transparencyColor); } - private List getCustomColors() { + public static List getCustomColors(@NonNull OsmandApplication app) { List colors = new ArrayList<>(); List colorNames = app.getSettings().CUSTOM_TRACK_COLORS.getStringsList(); if (colorNames != null) { diff --git a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java index 0c7cfce551..f8a9ebbfc3 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java @@ -38,6 +38,8 @@ import net.osmand.plus.UiUtilities.DialogButtonType; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.ContextMenuScrollFragment; import net.osmand.plus.dialogs.GpxAppearanceAdapter; +import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem; +import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; @@ -58,6 +60,7 @@ import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_BOLD; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_MEDIUM; +import static net.osmand.plus.dialogs.GpxAppearanceAdapter.getAppearanceItems; public class TrackAppearanceFragment extends ContextMenuScrollFragment implements CardListener, ColorPickerListener { @@ -80,6 +83,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement private TrackWidthCard trackWidthCard; private SplitIntervalCard splitIntervalCard; private TrackColoringCard trackColoringCard; + private ColorsCard colorsCard; private boolean showStartFinishIconsInitialValue; private ImageView trackIcon; @@ -339,7 +343,9 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement if (mapActivity != null) { if (card instanceof SplitIntervalCard) { SplitIntervalBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), trackDrawInfo, this); - } else if (card instanceof TrackColoringCard) { + } else if (card instanceof ColorsCard) { + int color = ((ColorsCard) card).getSelectedColor(); + trackDrawInfo.setColor(color); updateColorItems(); } else if (card instanceof TrackWidthCard) { updateAppearanceIcon(); @@ -356,7 +362,15 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement @Override public void onColorSelected(Integer prevColor, int newColor) { - trackColoringCard.onColorSelected(prevColor, newColor); + if (prevColor != null) { + List customColors = ColorsCard.getCustomColors(app); + int index = customColors.indexOf(prevColor); + if (index != ColorsCard.INVALID_VALUE) { + saveCustomColorsToTracks(prevColor, newColor); + } + } + trackDrawInfo.setColor(newColor); + colorsCard.onColorSelected(prevColor, newColor); updateColorItems(); } @@ -475,6 +489,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement AndroidUiHelper.updateVisibility(saveButton, true); AndroidUiHelper.updateVisibility(view.findViewById(R.id.buttons_divider), true); } + private void showShadowButton() { buttonsShadow.setVisibility(View.VISIBLE); buttonsShadow.animate() @@ -511,11 +526,30 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement AndroidUiHelper.updateVisibility(buttonsShadow, scrollToBottomAvailable); } + private void saveCustomColorsToTracks(int prevColor, int newColor) { + List gpxDataItems = app.getGpxDbHelper().getItems(); + for (GpxDataItem dataItem : gpxDataItems) { + if (prevColor == dataItem.getColor()) { + app.getGpxDbHelper().updateColor(dataItem, newColor); + } + } + List files = app.getSelectedGpxHelper().getSelectedGPXFiles(); + for (SelectedGpxFile selectedGpxFile : files) { + if (prevColor == selectedGpxFile.getGpxFile().getColor(0)) { + selectedGpxFile.getGpxFile().setColor(newColor); + } + } + } + private void updateColorItems() { updateAppearanceIcon(); if (trackWidthCard != null) { trackWidthCard.updateItems(); } + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.refreshMap(); + } } private void saveTrackInfo() { @@ -627,6 +661,8 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement trackColoringCard.setListener(this); cardsContainer.addView(trackColoringCard.build(mapActivity)); + setupColorsCard(cardsContainer); + trackWidthCard = new TrackWidthCard(mapActivity, trackDrawInfo, new OnNeedScrollListener() { @Override @@ -647,6 +683,26 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement } } + private void setupColorsCard(ViewGroup cardsContainer) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + List colors = getTrackColors(); + colorsCard = new ColorsCard(mapActivity, trackDrawInfo.getColor(), this, colors); + colorsCard.setListener(this); + cardsContainer.addView(colorsCard.build(mapActivity)); + } + } + + private List getTrackColors() { + List colors = new ArrayList<>(); + for (AppearanceListItem appearanceListItem : getAppearanceItems(app, GpxAppearanceAdapterType.TRACK_COLOR)) { + if (!colors.contains(appearanceListItem.getColor())) { + colors.add(appearanceListItem.getColor()); + } + } + return colors; + } + public List getGpxDisplayGroups() { GPXFile gpxFile = selectedGpxFile.getGpxFile(); if (gpxFile == null) { diff --git a/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java b/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java index 99571dad6c..0a17f5e06b 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java @@ -1,53 +1,36 @@ package net.osmand.plus.track; -import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; -import androidx.annotation.ColorInt; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.appcompat.content.res.AppCompatResources; import androidx.core.content.ContextCompat; -import androidx.core.graphics.ColorUtils; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.RecyclerView; -import com.google.android.material.internal.FlowLayout; - import net.osmand.AndroidUtils; import net.osmand.PlatformUtil; -import net.osmand.plus.GPXDatabase.GpxDataItem; -import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; -import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.dialogs.GpxAppearanceAdapter; -import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem; -import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routepreparationmenu.cards.BaseCard; -import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener; -import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; import java.util.ArrayList; import java.util.List; -public class TrackColoringCard extends BaseCard implements ColorPickerListener { +public class TrackColoringCard extends BaseCard { private static final int MINIMUM_CONTRAST_RATIO = 3; - public static final int INVALID_VALUE = -1; - private final static String SOLID_COLOR = "solid_color"; private static final Log log = PlatformUtil.getLog(TrackColoringCard.class); @@ -57,7 +40,6 @@ public class TrackColoringCard extends BaseCard implements ColorPickerListener { private TrackAppearanceItem selectedAppearanceItem; private List appearanceItems; - private List customColors; private Fragment target; public TrackColoringCard(MapActivity mapActivity, TrackDrawInfo trackDrawInfo, Fragment target) { @@ -65,7 +47,6 @@ public class TrackColoringCard extends BaseCard implements ColorPickerListener { this.target = target; this.trackDrawInfo = trackDrawInfo; appearanceItems = getGradientAppearanceItems(); - customColors = getCustomColors(); } @Override @@ -76,8 +57,6 @@ public class TrackColoringCard extends BaseCard implements ColorPickerListener { @Override protected void updateContent() { updateHeader(); - createColorSelector(); - updateColorSelector(); // coloringAdapter = new TrackColoringAdapter(appearanceItems); // RecyclerView groupRecyclerView = view.findViewById(R.id.recycler_view); @@ -87,25 +66,6 @@ public class TrackColoringCard extends BaseCard implements ColorPickerListener { AndroidUiHelper.updateVisibility(view.findViewById(R.id.top_divider), isShowDivider()); } - private List getCustomColors() { - List colors = new ArrayList<>(); - List colorNames = app.getSettings().CUSTOM_TRACK_COLORS.getStringsList(); - if (colorNames != null) { - for (String colorHex : colorNames) { - try { - if (!Algorithms.isEmpty(colorHex)) { - int color = Algorithms.parseColor(colorHex); - colors.add(color); - } - } catch (IllegalArgumentException e) { - log.error(e); - } - } - } - - return colors; - } - private List getGradientAppearanceItems() { List items = new ArrayList<>(); items.add(new TrackAppearanceItem(SOLID_COLOR, app.getString(R.string.track_coloring_solid), R.drawable.ic_action_circle)); @@ -117,138 +77,6 @@ public class TrackColoringCard extends BaseCard implements ColorPickerListener { return items; } - private void createColorSelector() { - FlowLayout selectColor = view.findViewById(R.id.select_color); - selectColor.removeAllViews(); - - for (int color : customColors) { - selectColor.addView(createColorItemView(color, selectColor, true)); - } - if (customColors.size() < 6) { - selectColor.addView(createAddCustomColorItemView(selectColor)); - } - selectColor.addView(createDividerView(selectColor)); - - List colors = new ArrayList<>(); - for (AppearanceListItem appearanceListItem : GpxAppearanceAdapter.getAppearanceItems(app, GpxAppearanceAdapterType.TRACK_COLOR)) { - if (!colors.contains(appearanceListItem.getColor())) { - colors.add(appearanceListItem.getColor()); - } - } - for (int color : colors) { - selectColor.addView(createColorItemView(color, selectColor, false)); - } - updateColorSelector(trackDrawInfo.getColor(), selectColor); - } - - private View createColorItemView(@ColorInt final int color, final FlowLayout rootView, boolean customColor) { - View colorItemView = createCircleView(rootView); - - ImageView backgroundCircle = colorItemView.findViewById(R.id.background); - - Drawable transparencyIcon = getTransparencyIcon(app, color); - Drawable colorIcon = app.getUIUtilities().getPaintedIcon(R.drawable.bg_point_circle, color); - Drawable layeredIcon = UiUtilities.getLayeredIcon(transparencyIcon, colorIcon); - double contrastRatio = ColorUtils.calculateContrast(color, ContextCompat.getColor(app, nightMode ? R.color.card_and_list_background_dark : R.color.card_and_list_background_light)); - if (contrastRatio < MINIMUM_CONTRAST_RATIO) { - backgroundCircle.setBackgroundResource(nightMode ? R.drawable.circle_contour_bg_dark : R.drawable.circle_contour_bg_light); - } - backgroundCircle.setImageDrawable(layeredIcon); - backgroundCircle.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - updateColorSelector(color, rootView); -// coloringAdapter.notifyDataSetChanged(); - trackDrawInfo.setColor(color); - - CardListener listener = getListener(); - if (listener != null) { - listener.onCardPressed(TrackColoringCard.this); - } - } - }); - if (customColor) { - backgroundCircle.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - CustomColorBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), target, color); - } - return false; - } - }); - } - colorItemView.setTag(color); - return colorItemView; - } - - private Drawable getTransparencyIcon(OsmandApplication app, @ColorInt int color) { - int colorWithoutAlpha = UiUtilities.removeAlpha(color); - int transparencyColor = UiUtilities.getColorWithAlpha(colorWithoutAlpha, 0.8f); - return app.getUIUtilities().getPaintedIcon(R.drawable.ic_bg_transparency, transparencyColor); - } - - private View createAddCustomColorItemView(FlowLayout rootView) { - View colorItemView = createCircleView(rootView); - ImageView backgroundCircle = colorItemView.findViewById(R.id.background); - - int bgColorId = nightMode ? R.color.activity_background_color_dark : R.color.activity_background_color_light; - Drawable backgroundIcon = app.getUIUtilities().getIcon(R.drawable.bg_point_circle, bgColorId); - - ImageView icon = colorItemView.findViewById(R.id.icon); - icon.setVisibility(View.VISIBLE); - int activeColorResId = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; - icon.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_plus, activeColorResId)); - - backgroundCircle.setImageDrawable(backgroundIcon); - backgroundCircle.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - CustomColorBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), target, null); - } - } - }); - return colorItemView; - } - - private View createDividerView(FlowLayout rootView) { - LayoutInflater themedInflater = UiUtilities.getInflater(view.getContext(), nightMode); - View divider = themedInflater.inflate(R.layout.simple_divider_item, rootView, false); - - LinearLayout dividerContainer = new LinearLayout(view.getContext()); - dividerContainer.addView(divider); - dividerContainer.setPadding(0, AndroidUtils.dpToPx(app, 1), 0, AndroidUtils.dpToPx(app, 5)); - - return dividerContainer; - } - - private View createCircleView(ViewGroup rootView) { - LayoutInflater themedInflater = UiUtilities.getInflater(view.getContext(), nightMode); - View circleView = themedInflater.inflate(R.layout.point_editor_button, rootView, false); - ImageView outline = circleView.findViewById(R.id.outline); - int colorId = nightMode ? R.color.stroked_buttons_and_links_outline_dark : R.color.stroked_buttons_and_links_outline_light; - Drawable contourIcon = app.getUIUtilities().getIcon(R.drawable.bg_point_circle_contour, colorId); - outline.setImageDrawable(contourIcon); - return circleView; - } - - private void updateColorSelector(int color, View rootView) { - View oldColor = rootView.findViewWithTag(trackDrawInfo.getColor()); - if (oldColor != null) { - oldColor.findViewById(R.id.outline).setVisibility(View.INVISIBLE); - ImageView icon = oldColor.findViewById(R.id.icon); - icon.setImageDrawable(UiUtilities.tintDrawable(icon.getDrawable(), R.color.icon_color_default_light)); - } - View newColor = rootView.findViewWithTag(color); - if (newColor != null) { - newColor.findViewById(R.id.outline).setVisibility(View.VISIBLE); - } - mapActivity.refreshMap(); - } - private TrackAppearanceItem getSelectedAppearanceItem() { if (selectedAppearanceItem == null) { GradientScaleType scaleType = trackDrawInfo.getGradientScaleType(); @@ -293,49 +121,6 @@ public class TrackColoringCard extends BaseCard implements ColorPickerListener { updateColorSelector(); } - @Override - public void onColorSelected(Integer prevColor, int newColor) { - if (prevColor != null) { - int index = customColors.indexOf(prevColor); - if (index != INVALID_VALUE) { - customColors.set(index, newColor); - saveCustomColorsToTracks(prevColor, newColor); - } - if (trackDrawInfo.getColor() == prevColor) { - trackDrawInfo.setColor(newColor); - } - } else if (customColors.size() < 6) { - customColors.add(newColor); - trackDrawInfo.setColor(newColor); - } - saveCustomColors(); - updateContent(); - } - - private void saveCustomColorsToTracks(int prevColor, int newColor) { - List gpxDataItems = app.getGpxDbHelper().getItems(); - for (GpxDataItem dataItem : gpxDataItems) { - if (prevColor == dataItem.getColor()) { - app.getGpxDbHelper().updateColor(dataItem, newColor); - } - } - List files = app.getSelectedGpxHelper().getSelectedGPXFiles(); - for (SelectedGpxFile selectedGpxFile : files) { - if (prevColor == selectedGpxFile.getGpxFile().getColor(0)) { - selectedGpxFile.getGpxFile().setColor(newColor); - } - } - } - - private void saveCustomColors() { - List colorNames = new ArrayList<>(); - for (Integer color : customColors) { - String colorHex = Algorithms.colorToString(color); - colorNames.add(colorHex); - } - app.getSettings().CUSTOM_TRACK_COLORS.setStringsList(colorNames); - } - private class TrackColoringAdapter extends RecyclerView.Adapter { private List items; From 3a6e8ce977e4d8e4daf62aff72fe16ee7c06fe3c Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Mon, 2 Nov 2020 09:58:53 +0200 Subject: [PATCH 036/106] Fix imported item icon --- .../settings/fragments/ImportedSettingsItemsAdapter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportedSettingsItemsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportedSettingsItemsAdapter.java index d50b00ae6f..1c30923de4 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportedSettingsItemsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportedSettingsItemsAdapter.java @@ -130,6 +130,14 @@ public class ImportedSettingsItemsAdapter extends holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_map, activeColorRes)); holder.title.setText(R.string.shared_string_local_maps); break; + case TTS_VOICE: + holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_volume_up, activeColorRes)); + holder.title.setText(R.string.local_indexes_cat_tts); + break; + case VOICE: + holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_volume_up, activeColorRes)); + holder.title.setText(R.string.local_indexes_cat_voice); + break; case GLOBAL: holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_settings, activeColorRes)); holder.title.setText(R.string.general_settings_2); From ca6e5413d1e5418c72e321da42eb750e643f3078 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Mon, 2 Nov 2020 13:52:16 +0200 Subject: [PATCH 037/106] small fixes after SettingsBaseActivity removed --- OsmAnd/res/values/strings.xml | 1 + .../plus/measurementtool/graph/CustomGraphAdapter.java | 7 +++---- .../plus/routepreparationmenu/cards/RouteInfoCard.java | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 7861393b31..91eec18222 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,7 @@ Thx - Hardy --> + You must add at least two points. Travel Emergency Sport diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java index aded2e0fbe..e62047c151 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java @@ -22,7 +22,6 @@ import net.osmand.AndroidUtils; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.activities.SettingsNavigationActivity; import net.osmand.plus.helpers.CustomBarChartRenderer; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.router.RouteStatisticsHelper; @@ -34,9 +33,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -public class CustomGraphAdapter extends BaseGraphAdapter { +import static net.osmand.plus.track.ColorsCard.MINIMUM_CONTRAST_RATIO; - private static final int MINIMUM_CONTRAST_RATIO = 3; +public class CustomGraphAdapter extends BaseGraphAdapter { private String selectedPropertyName; private ViewGroup legendContainer; @@ -153,7 +152,7 @@ public class CustomGraphAdapter extends BaseGraphAdapter Date: Mon, 2 Nov 2020 13:45:34 +0000 Subject: [PATCH 038/106] Translated using Weblate (Catalan) Currently translated at 97.2% (3428 of 3524 strings) --- OsmAnd/res/values-ca/strings.xml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-ca/strings.xml b/OsmAnd/res/values-ca/strings.xml index eb412908d1..47a7b77639 100644 --- a/OsmAnd/res/values-ca/strings.xml +++ b/OsmAnd/res/values-ca/strings.xml @@ -184,7 +184,7 @@ Seleccioneu una veu i comproveu les seves indicacions: Canvia el zoom del mapa seguint el desplaçament horitzontal del ratolí de bola. Utilitza el ratolí de bola per controlar el zoom - Es van pujar {0} PDI/notes + S\'han pujat {0} PDI/notes PDIs/notes d\'OSM desades al dispositiu Mostra i gestiona els PDI/notes d\'OSM de la vostra base de dades local. Informació de dia/nit @@ -3859,4 +3859,24 @@ Abasta l\'àrea: %1$s x %2$s Control de pantalla Desenvolupament %1$s — %2$s + Canvieu al càlcul amb Java (segur) de rutes de Transport Public + Icones d\'Inici/Final + Gràcies per comprar \'Corbes de nivell\' + Evita els camins per a vianants + Evita els camins per a vianants + Dades d\'OsmAnd Live + Dades d\'OsmAnd Live + Enrutament en dues fases per navegació amb cotxe. + Inicieu la sessió mitjançant OAuth per fer servir les funcionalitats osmedit + Inicieu la sessió via OAuth + Neteja el testimoni OAuth d\'OpenStreetMap + La sessió s\'ha tancat correctament + El fitxer ja s\'ha importat a OsmAnd + Mapes locals + Especial + Transport + Servei + Símbols + Esport + Emergència \ No newline at end of file From 17f9ea44786041d83d47638cf165ec2937b3e576 Mon Sep 17 00:00:00 2001 From: josep constanti Date: Mon, 2 Nov 2020 13:48:33 +0000 Subject: [PATCH 039/106] Translated using Weblate (Catalan) Currently translated at 97.2% (3428 of 3524 strings) --- OsmAnd/res/values-ca/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/res/values-ca/strings.xml b/OsmAnd/res/values-ca/strings.xml index 47a7b77639..17ed9cdcb9 100644 --- a/OsmAnd/res/values-ca/strings.xml +++ b/OsmAnd/res/values-ca/strings.xml @@ -3859,7 +3859,7 @@ Abasta l\'àrea: %1$s x %2$s Control de pantalla Desenvolupament %1$s — %2$s - Canvieu al càlcul amb Java (segur) de rutes de Transport Public + Canvieu el càlcul de rutes de Transport Public a Java (segur) Icones d\'Inici/Final Gràcies per comprar \'Corbes de nivell\' Evita els camins per a vianants From e736c5e3dd2fcfd94f516b865725d978659e784c Mon Sep 17 00:00:00 2001 From: ffff23 Date: Sun, 1 Nov 2020 15:42:44 +0000 Subject: [PATCH 040/106] Translated using Weblate (Japanese) Currently translated at 97.7% (3446 of 3524 strings) --- OsmAnd/res/values-ja/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/res/values-ja/strings.xml b/OsmAnd/res/values-ja/strings.xml index bbdfcef055..ef429b88a7 100644 --- a/OsmAnd/res/values-ja/strings.xml +++ b/OsmAnd/res/values-ja/strings.xml @@ -3206,7 +3206,7 @@ POIの更新は利用できません マップ外観 インストール済みプラグインリスト ナビゲーション設定 - アプリテーマ、ユニット、リージョン + アプリテーマ、単位、地域 プロファイルの構築 プロファイル切替 アプリケーションプロファイルが\"%s\"に切り替えられました From bfa0f280cce49b6e583ef54ea1bdf659fce5e1d6 Mon Sep 17 00:00:00 2001 From: Simon Legner Date: Sun, 1 Nov 2020 09:31:30 +0000 Subject: [PATCH 041/106] Translated using Weblate (German) Currently translated at 99.8% (3519 of 3524 strings) --- OsmAnd/res/values-de/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index 559fb70a06..1a1693eee7 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -3937,4 +3937,13 @@ 2-Phasen-A*-Routing-Algorithmus verwenden %1$s Daten sind nur auf den Straßen verfügbar, Sie müssen eine Route mit \"Route zwischen Punkten\" berechnen, um sie zu erhalten. %1$s — %2$s + MGRS + Warte auf die Neuberechnung der Route. +\nDie Graphik wird nach der Neuberechnung verfügbar sein. + Ausstattung + ÖPNV + Dienstleistung + Reisen + Sport + Notfall \ No newline at end of file From 513a800a3f16f013996878b80a6c4d9503e66451 Mon Sep 17 00:00:00 2001 From: Franco Date: Sun, 1 Nov 2020 13:27:37 +0000 Subject: [PATCH 042/106] Translated using Weblate (Spanish) Currently translated at 98.2% (3463 of 3524 strings) --- OsmAnd/res/values-es/strings.xml | 46 +++++++++++++++++--------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/OsmAnd/res/values-es/strings.xml b/OsmAnd/res/values-es/strings.xml index 6041f2a95e..efe9166106 100644 --- a/OsmAnd/res/values-es/strings.xml +++ b/OsmAnd/res/values-es/strings.xml @@ -609,18 +609,18 @@ Usa mapas en línea (descarga y guarda teselas en la tarjeta de memoria). Mapas en línea Elige las fuentes de teselas de mapas en línea o en caché. - "Accede a muchos tipos de mapas en línea (llamados teselas o ráster), desde teselas predefinidas de OpenStreetMap (como Mapnik) a imágenes satelitales y capas de propósito especial como mapas meteorológicos, mapas del clima, mapas geológicos, capas de sombreado, etc. + Accede a muchos tipos de mapas en línea (llamados teselas o ráster), desde teselas predefinidas de OpenStreetMap (como Mapnik) a imágenes satelitales y capas de propósito especial como mapas meteorológicos, mapas del clima, mapas geológicos, capas de sombreado, etc. \n \nCualquiera de estos mapas puede mostrarse como el mapa (base) principal, o como una superposición o subyacencia de otro mapa base (como los mapas estándar de OsmAnd sin conexión). Ciertos elementos de los mapas vectoriales OsmAnd se pueden ocultar a través del menú «Configurar mapa» para hacer más visible cualquier mapa subyacente. \n -\nDescarga los mapas de teselas directamente a través de fuentes en línea, o prepararlos para tu uso sin conexión (copiándolos manualmente en la carpeta de datos OsmAnd) como una base de datos SQLite que puede generarse con varias herramientas de preparación de mapas de terceros." +\nDescarga los mapas de teselas directamente a través de fuentes en línea, o prepararlos para tu uso sin conexión (copiándolos manualmente en la carpeta de datos OsmAnd) como una base de datos SQLite que puede generarse con varias herramientas de preparación de mapas de terceros. Muestra los ajustes para activar en modo reposo el seguimiento y la navegación, activando periódicamente el dispositivo GPS (con la pantalla apagada). Activa las funciones de accesibilidad del dispositivo directamente en OsmAnd. Facilita por ejemplo, el ajuste de la velocidad de la voz para voces de texto a voz, la configuración de navegación de pantalla con el panel direccional, usando la rueda de desplazamiento para el control del zoom, o la retroalimentación de texto a voz, por ejemplo, para anunciar la ubicación automáticamente. Este complemento muestra los ajustes de funciones de desarrollo y depuración para probar la simulación de rutas, el rendimiento del renderizado, o las indicaciones por voz. Estos ajustes están destinados para los desarrolladores y no son necesarios para el usuario general. Complementos Los complementos activan ajustes avanzados y funcionalidades adicionales. Complementos - Este complemento puede usarse para hacer contribuciones en OSM, como el crear o modificar objetos PDI, abrir o comentar notas de OSM y contribuir con archivos de trazas GPX. OSM es un proyecto de mapeo global impulsado por la comunidad y de dominio público. Para más detalles, consulta https://openstreetmap.org. Se aprecia la participación activa, y las contribuciones pueden hacerse directamente desde OsmAnd, especificando las credenciales personales de OSM en la aplicación. + Haz contribuciones en OSM, como el crear o modificar objetos PDI, abrir o comentar notas de OSM y contribuir con archivos de trazas GPX grabados en OsmAnd, proporcionando tu nombre de usuario y contraseña. OpenStreetMap.org es un proyecto de mapeo de dominio público, global, libre e impulsado por la comunidad. Los mapas vectoriales pueden mostrarse más rápido. Puede no funcionar correctamente en algunos dispositivos. Elige una voz y reproduce pruebas de los avisos: Desarrollo de OsmAnd @@ -890,8 +890,8 @@ Tomar notas de audio/foto/video durante un viaje, usando un botón de mapa o un menú contextual de la ubicación. Notas audio/vídeo Complemento OsmAnd para curvas de nivel sin conexión - Este complemento proporciona una capa superpuesta de curvas de nivel y una capa (de relieve) sombreada, que se pueden visualizar sobre los mapas descargados de OsmAnd. Esta funcionalidad será muy apreciada por atletas, caminantes, excursionistas, y cualquiera interesado en la estructura de relieve de un paisaje. -\n + Proporciona una capa superpuesta de curvas de nivel y una capa (de relieve) sombreada, que se pueden visualizar sobre los mapas descargados de OsmAnd. Esta funcionalidad será muy apreciada por atletas, caminantes, excursionistas, y cualquiera interesado en la estructura de relieve de un paisaje. +\n \nLos datos globales (entre 70° norte y 70° sur) se basan en mediciones de SRTM (Shuttle Radar Topography Mission, o en español Misión de Topografía por Radar desde Transbordador) y ASTER (Advanced Spaceborne Thermal Emission and Reflection Radiometer, o en español Radiómetro Espacial Avanzado de Emisión Térmica y Reflexión), un instrumento de captura de imágenes a bordo de Terra, el satélite insignia del Sistema de Observación de la Tierra de la NASA. ASTER es un esfuerzo cooperativo entre la NASA, el Ministerio de Economía, Comercio e Industria de Japón (METI) y Sistemas Espaciales de Japón (J-spacesystems). Medición de distancia Pulsa «Usar ubicación…» para añadir una nota a la ubicación. @@ -3014,22 +3014,24 @@ Buscando GPS Widget de coordenadas OVNI - • Perfiles de aplicación: crea un perfil personalizado según tus necesidades, con un icono y color personalizado. -\n -\n • Ahora puedes personalizar las velocidades predefinidas, máximas y mínimas de cualquier perfil -\n -\n • Se ha añadido un widget para las coordenadas actuales -\n -\n • Se añadieron opciones para mostrar la brújula y una regla radial en el mapa -\n -\n • Se ha corregido la grabación de trazas en segundo plano -\n -\n • Se mejoraron las descargas de mapas en segundo plano -\n -\n • Se ha corregido la selección de idioma de Wikipedia -\n -\n • Se ha corregido el comportamiento de los botones de la brújula durante la navegación -\n + • Perfiles de aplicación: crea un perfil personalizado según tus necesidades, con un icono y color personalizado. +\n +\n • Ahora puedes personalizar las velocidades predefinidas, máximas y mínimas de cualquier perfil +\n +\n • Se ha añadido un widget para las coordenadas actuales +\n +\n • Se añadieron opciones para mostrar la brújula y una regla radial en el mapa +\n +\n • Se ha corregido la grabación de trazas en segundo plano +\n +\n • Se mejoraron las descargas de mapas en segundo plano +\n +\n • Se ha vuelto a añadir la opción «Encender pantalla» +\n +\n • Se ha corregido la selección de idioma de Wikipedia +\n +\n • Se ha corregido el comportamiento de los botones de la brújula durante la navegación +\n \n • Otras correcciones de errores \n \n @@ -3840,7 +3842,7 @@ Ruta inversa La traza completa será recalculada utilizando el perfil seleccionado. Sólo el siguiente segmento será recalculado usando el perfil seleccionado. - Selecciona cómo conectar puntos, con línea recta, o calcula una ruta entre ellos como se especifica a continuación. + Elija cómo conectar los puntos, en línea recta o calcular una ruta entre ellos como se especifica a continuación. Traza completa Siguiente segmento A continuación, ajusta tu traza a la carretera permitida más cercana con uno de tus perfiles de navegación para usar esta opción. From 903de8e1ab4c9825757a95240770ac5273405d95 Mon Sep 17 00:00:00 2001 From: Softmap Date: Sun, 1 Nov 2020 10:54:27 +0000 Subject: [PATCH 043/106] Translated using Weblate (Arabic) Currently translated at 100.0% (3524 of 3524 strings) --- OsmAnd/res/values-ar/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-ar/strings.xml b/OsmAnd/res/values-ar/strings.xml index 65c7a07411..5a04090668 100644 --- a/OsmAnd/res/values-ar/strings.xml +++ b/OsmAnd/res/values-ar/strings.xml @@ -3931,4 +3931,7 @@ رياضة الطوارئ سفر + النظام المرجعي للشبكة العسكرية + النظام المرجعي للشبكة العسكرية + OsmAnd يستخدم MGRS، وهو مشابه لتنسيق UTM NATO . \ No newline at end of file From b4b5c666739c10739582f33da9a7516909fe9292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Kotr=C4=8D?= Date: Sun, 1 Nov 2020 21:10:10 +0000 Subject: [PATCH 044/106] Translated using Weblate (Czech) Currently translated at 80.6% (2841 of 3524 strings) --- OsmAnd/res/values-cs/strings.xml | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/OsmAnd/res/values-cs/strings.xml b/OsmAnd/res/values-cs/strings.xml index 67044dc34e..0fd23b4381 100644 --- a/OsmAnd/res/values-cs/strings.xml +++ b/OsmAnd/res/values-cs/strings.xml @@ -3589,4 +3589,66 @@ Zobrazená oblast: %1$s x %2$s Počkejte na přepočet trasy. \nGraf bude dostupný po přepočtu. %1$s — %2$s + Pseudo-Mercatorovo zobrazení + Jeden obrazový soubor pro každou dlaždici + Soubor SQLiteDB + Zadejte název online zdroje. + Zadejte nebo vložte URL online zdroje. + Opravdu chcete odstranit %d rychlých akcí\? + Časový limit obrazovky + Odinstalovat rychlostní radary + Právní informace + Body rychlostních radarů + V některých zemích nebo regionech je zákonem zakázáno používat aplikace varující před rychlostními radary. +\n +\nMusíte se rozhodnout podle zákonů vaší země. +\n +\nZvolíte-li %1$s, budete dostávat varování před rychlostními radary. +\n +\nZvolíte-li %2$s, všechna data o rychlostních radarech budou odstraněna do té doby, než OsmAnd kompletně přeinstalujete. + Ponechat aktivní + Odinstalovat + V některých zemích je varování před rychlostními radary zákonem zakázané. + Je-li \"%1$s\" zapnuto, čas aktivity bude na tom záviset. + Výchozí časový limit obrazovky + tuny + metry + Zobrazit nebo skrýt další detaily na mapě + Noční mapa + Přidat online zdroj + Použitím těchto změn se vymažou uložené dlaždice pro tento zdroj + Nastavit výšku plavidla + Můžete nastavit výšku plavidla, aby bylo možné se vyhnout nízkým mostům. Mějte na paměti, že pro pohyblivé mosty se zohledňuje výška v otevřeném stavu. + Plné + Přepsat stopu + Uložit jako novou stopu + Otočit trasu + Celá stopa bude přepočítána pomocí zvoleného profilu. + Pouze následující úsek bude přepočítaný pomocí zvoleného profilu. + Zvolte, jakým způsobem spojit body – přímou čarou, nebo výpočtem trasy mezi nimi, viz níže. + Celá stopa + Další úsek + Předplatné bude účtováno za zvolené období. Můžete jej kdykoliv zrušit na AppGallery. + Platba se strhne z vašeho účtu AppGallery po potvrzení nákupu. +\n +\nPředplatné bude automaticky obnoveno, pokud jej před datem obnovení nezrušíte. Platba za další období (měsíc/čtvrtletí/rok) bude stržena pouze v den obnovení. +\n +\nPředplatné můžete spravovat a zrušit v nastavení AppGallery. + Vyhnout se chodníkům + Vyhnout se chodníkům + Vývoj + Údaje OsmAnd Live + Údaje OsmAnd Live + Dvoufázový výpočet trasy pro navigaci auta. + Nativní hromadná doprava (ve vývoji) + Přepnout na výpočet trasy hromadné dopravy v Javě (bezpečné) + Lokální mapy + Občanská vybavenost + Speciální + Doprava + Služby + Symboly + Sport + Nouzová situace + Cestování \ No newline at end of file From b5088cdabaa13422f9e909f047826a10184e1476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=BB=D0=B0=D0=BC=D0=B5=D0=BD?= Date: Sun, 1 Nov 2020 10:46:27 +0000 Subject: [PATCH 045/106] Translated using Weblate (Bulgarian) Currently translated at 47.3% (1668 of 3524 strings) --- OsmAnd/res/values-bg/strings.xml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-bg/strings.xml b/OsmAnd/res/values-bg/strings.xml index 813e23367c..2a02f5ee55 100644 --- a/OsmAnd/res/values-bg/strings.xml +++ b/OsmAnd/res/values-bg/strings.xml @@ -1710,7 +1710,7 @@ POI ще бъдат изтрити, след като качите Вашите промени Моля, кажете ни какви промени искате в това приложение. Вашето мнение е важно за нас. - Преизчисляване само началната част от дълги маршрути + Преизчисляване само на началото на маршрута. Може да се ползва за дълги маршрути. Онлайн OSM класификация на картите с изображения Показва използваните безплатни файлове за изтегляне Записването в GPX може да бъде включвано и изключвано от основния екран @@ -2187,4 +2187,29 @@ Аварийни служби Пътуване Изчистете маркера OAuth на OpenStreetMap + Всички предишни сегменти ще бъдат преизчислени спрямо избрания профил. + Отваряне на записан трак + е записан + Моля, добавете поне две точки. + Повтаряне + Последна промяна + Име: Я - А + Име: А - Я + Икони за начало/край + Благодарим ви, че закупихте \"Контурни линии\" + Абонаментът се таксува за избрания период. Можете да го отмените в AppGallery по всяко време. + Заплащането ще ви бъде приспаднато от вашия акаунт в AppGallery при потвърждаване на покупката. +\n +\nАбонаментът се удължава автоматично, ако не бъде отменен преди датата на подновяване. От вашата сметка се удържат пари само в датата на подновяване. +\n +\nМожете да управлявате или да прекъснете абонаментите си в настройките на AppGallery. + Избягване на пътеки + Избягване на пътеки + Разработка + Данни на OsmAnd Live + Данни на OsmAnd Live + Двустъпково изчисляване на маршрута за автомобилна навигация. + Превключете на Java (безопасен режим) изчисляването на маршрути за обществения транспорт + Влезте с OAuth, за да ползвате всички функции на osmedit + Вход с OAuth \ No newline at end of file From 187b0dc3a17aebea29f9a4758b57e35a788d00fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Kotr=C4=8D?= Date: Sun, 1 Nov 2020 20:38:09 +0000 Subject: [PATCH 046/106] Translated using Weblate (Czech) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-cs/phrases.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-cs/phrases.xml b/OsmAnd/res/values-cs/phrases.xml index b64efe0702..fc5bfd5892 100644 --- a/OsmAnd/res/values-cs/phrases.xml +++ b/OsmAnd/res/values-cs/phrases.xml @@ -3849,4 +3849,5 @@ Přístřešky Střešní Bod GPX + Radarová věž \ No newline at end of file From a5b48a702b42b4056e685dad41cc90e53e43dd3b Mon Sep 17 00:00:00 2001 From: ffff23 Date: Mon, 2 Nov 2020 12:54:21 +0000 Subject: [PATCH 047/106] Translated using Weblate (Japanese) Currently translated at 99.3% (3807 of 3830 strings) --- OsmAnd/res/values-ja/phrases.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-ja/phrases.xml b/OsmAnd/res/values-ja/phrases.xml index 3ddebc7b5a..4dd597c4ae 100644 --- a/OsmAnd/res/values-ja/phrases.xml +++ b/OsmAnd/res/values-ja/phrases.xml @@ -3839,4 +3839,5 @@ 待避所 車庫 屋上 + レーダー塔 \ No newline at end of file From a4c457dfc3393ad07a78809d6412cbe05c26897f Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Sun, 1 Nov 2020 02:26:55 +0000 Subject: [PATCH 048/106] Translated using Weblate (Ukrainian) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-uk/phrases.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-uk/phrases.xml b/OsmAnd/res/values-uk/phrases.xml index 0faed8c3ad..e3387de728 100644 --- a/OsmAnd/res/values-uk/phrases.xml +++ b/OsmAnd/res/values-uk/phrases.xml @@ -3837,4 +3837,5 @@ Навіси Дах Точка GPX + Радіолокаційна вежа \ No newline at end of file From cb309264d16afa548cc93fbe6beba14a81723a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sun, 1 Nov 2020 08:31:28 +0000 Subject: [PATCH 049/106] Translated using Weblate (Estonian) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-et/phrases.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-et/phrases.xml b/OsmAnd/res/values-et/phrases.xml index 4e06dceeb0..3989f35f69 100644 --- a/OsmAnd/res/values-et/phrases.xml +++ b/OsmAnd/res/values-et/phrases.xml @@ -3831,4 +3831,5 @@ Parkla kiirtee ääres Parkimine varjualustes Parkla katusel + Radarimast \ No newline at end of file From 6442d47593e70d728dbaec0ebf50ef39d3eee4ce Mon Sep 17 00:00:00 2001 From: Franco Date: Sun, 1 Nov 2020 13:12:28 +0000 Subject: [PATCH 050/106] Translated using Weblate (Spanish) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-es/phrases.xml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/OsmAnd/res/values-es/phrases.xml b/OsmAnd/res/values-es/phrases.xml index cac7b4a36d..925fc45bb3 100644 --- a/OsmAnd/res/values-es/phrases.xml +++ b/OsmAnd/res/values-es/phrases.xml @@ -1868,7 +1868,7 @@ 100LL (con plomo, para aviones) Autogas (Etanol libre de plomo) Jet A-1 (diésel) - Líquido de escape de diesel + Aditivo para escapes de Diesel (AdBlue) Combustible: madera Combustible: carbón vegetal Combustible: carbón @@ -3562,8 +3562,8 @@ Radioterapia Advertencia de peligro Categoría de dificultad - н/к (sin categoría) - н/к* (sin categoría, posible peligro) + s/c (sin categoría) + s/c* (sin categoría, posible peligro) 1А* 1B @@ -3808,7 +3808,7 @@ Nivel de agua: parcialmente sumergido Incorrecto Sólo se permite al caminar - Señal para encontrar el poste + Acceso a Internet: clientes Tipo de cabina Cabina Centro de buceo @@ -3845,4 +3845,10 @@ Pequeños electrodomésticos Tablero de salidas Relleno de agua potable + Torre de radar + Apartadero + Cobertizos + Azotea + Punto GPX + Gas natural licuado \ No newline at end of file From 46c8fd25a14a155d73da87d01090f706555579f1 Mon Sep 17 00:00:00 2001 From: Franco Date: Sun, 1 Nov 2020 13:25:34 +0000 Subject: [PATCH 051/106] Translated using Weblate (Spanish (Argentina)) Currently translated at 99.9% (3523 of 3524 strings) --- OsmAnd/res/values-es-rAR/strings.xml | 39 ++++++++++++++++------------ 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index 54e7d2a41b..e29831c83a 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -3121,22 +3121,24 @@ Error OsmAnd falló la última vez. Por favor, ayúdanos a mejorar OsmAnd compartiendo el mensaje de error. OVNI - • Perfiles de aplicación: crea un perfil personalizado según tus necesidades, con un icono y color personalizado -\n -\n • Ahora puedes personalizar las velocidades predefinidas, máximas y mínimas de cualquier perfil -\n -\n • Se ha añadido un widget para las coordenadas actuales -\n -\n • Se añadieron opciones para mostrar la brújula y una regla radial en el mapa -\n -\n • Se ha corregido la grabación de trazas en segundo plano -\n -\n • Se mejoraron las descargas de mapas en segundo plano -\n -\n • Se ha corregido la selección de idioma de Wikipedia -\n -\n • Se ha corregido el comportamiento de los botones de la brújula durante la navegación -\n + • Perfiles de aplicación: crea un perfil personalizado según tus necesidades, con un icono y color personalizado. +\n +\n • Ahora puedes personalizar las velocidades predefinidas, máximas y mínimas de cualquier perfil +\n +\n • Se ha añadido un widget para las coordenadas actuales +\n +\n • Se añadieron opciones para mostrar la brújula y una regla radial en el mapa +\n +\n • Se ha corregido la grabación de trazas en segundo plano +\n +\n • Se mejoraron las descargas de mapas en segundo plano +\n +\n • Se ha vuelto a añadir la opción «Encender pantalla» +\n +\n • Se ha corregido la selección de idioma de Wikipedia +\n +\n • Se ha corregido el comportamiento de los botones de la brújula durante la navegación +\n \n • Otras correcciones de errores \n \n @@ -3551,7 +3553,7 @@ Guardando el nuevo perfil No se pudo respaldar el perfil. ¿Borrar los datos registrados\? - Importando de datos de «%1$s» + Importando datos de «%1$s» Importando OsmAnd comprueba %1$s para ver si hay duplicados con los elementos existentes en la aplicación. \n @@ -3946,4 +3948,7 @@ Deporte Emergencia Viaje + MGRS + MGRS + OsmAnd usa MGRS, similar al formato UTM de la OTAN. \ No newline at end of file From 12bf9e082e1ea6c4bc7e6066fdf7b3ff3685d5ca Mon Sep 17 00:00:00 2001 From: Franco Date: Sun, 1 Nov 2020 13:02:45 +0000 Subject: [PATCH 052/106] Translated using Weblate (Spanish (Argentina)) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-es-rAR/phrases.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OsmAnd/res/values-es-rAR/phrases.xml b/OsmAnd/res/values-es-rAR/phrases.xml index 9f3c0b8803..20712137c0 100644 --- a/OsmAnd/res/values-es-rAR/phrases.xml +++ b/OsmAnd/res/values-es-rAR/phrases.xml @@ -3047,7 +3047,7 @@ Shawarma;Carne a las brasas en asador horizontal Estación de combustible náutica;Gasolinera náutica Cebadero para animales - Artículos de cotillón;Artículos para fiestas + Artículos para fiestas;Cotillón Artículos de electricidad Cerrajería Artículos de iluminación @@ -3206,7 +3206,7 @@ Cañón (desfiladero) Couloir (barranco estrecho y empinado) Área montañosa - Polvo de ladrillo + Polvo de ladrillo (arcilla) Tartán Césped artificial Decoturf (superficie dura para tenis) @@ -3856,4 +3856,5 @@ Cobertizos Azotea Punto GPX + Torre de radar \ No newline at end of file From f7138c0c426718e325bc5071389bed71546966a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sun, 1 Nov 2020 09:01:31 +0000 Subject: [PATCH 053/106] Translated using Weblate (Estonian) Currently translated at 99.2% (3499 of 3524 strings) --- OsmAnd/res/values-et/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-et/strings.xml b/OsmAnd/res/values-et/strings.xml index 2a0af4fbbf..f1fbad6379 100644 --- a/OsmAnd/res/values-et/strings.xml +++ b/OsmAnd/res/values-et/strings.xml @@ -3795,4 +3795,7 @@ Sümbolid Teenused Transport + OsmAnd kasutab MGRS-vormingut, mis on sarnane NATO UTM-vormingule. + MGRS + MGRS \ No newline at end of file From d4d6a29887d2af56d97a0a6bb133b85b9d95e5e0 Mon Sep 17 00:00:00 2001 From: Franco Date: Sun, 1 Nov 2020 12:48:43 +0000 Subject: [PATCH 054/106] Translated using Weblate (Spanish (American)) Currently translated at 99.9% (3523 of 3524 strings) --- OsmAnd/res/values-es-rUS/strings.xml | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/OsmAnd/res/values-es-rUS/strings.xml b/OsmAnd/res/values-es-rUS/strings.xml index 8cbb5a9aeb..746343005d 100644 --- a/OsmAnd/res/values-es-rUS/strings.xml +++ b/OsmAnd/res/values-es-rUS/strings.xml @@ -3551,14 +3551,14 @@ Guardando el nuevo perfil No se pudo respaldar el perfil. ¿Borrar los datos registrados\? - Importación de datos de %1$s - Importación + Importando datos de «%1$s» + Importando OsmAnd comprueba %1$s para ver si hay duplicados con los elementos existentes en la aplicación. \n \nPuede llevar algún tiempo. Elementos añadidos Importación completa - Todos los datos de %1$s son importados, puedes usar los botones de abajo para abrir la parte necesaria de la aplicación para manejarla. + Todos los datos de «%1$s» fueron importados. Puedes usar los botones de abajo para gestionar la sección necesaria de la aplicación. Terreno Mapa de sombreado usando sombras oscuras para mostrar las laderas, picos y tierras bajas. La pendiente utiliza colores para visualizar la inclinación del terreno. @@ -3838,7 +3838,7 @@ Recalcular toda la traza usando el perfil elegido. A continuación, ajusta la traza al camino permitido más cercano con un perfil de navegación. Recalcular sólo el siguiente segmento usando el perfil elegido. - Marca cómo conectar los puntos, con una línea recta o calcular una ruta entre ellos como se detalla a continuación. + Elige cómo conectar los puntos, con una línea recta o calcular una ruta entre ellos como se detalla a continuación. Elige un archivo de traza al que se añadirá un nuevo segmento. Ruta inversa Añadir punto de referencia de la traza @@ -3926,4 +3926,24 @@ Desarrollo Navegación bifásica en automóvil. Vaciar llave OAuth de OpenStreetMap + Usar el algoritmo de navegación A* bifásica + Para caminos y senderos exclusivos de motos de nieve. + Mapas locales + Gráfico + MGRS + MGRS + OsmAnd usa MGRS, similar al formato UTM de la OTAN. + %1$s datos disponibles sólo en los caminos, necesitas calcular una ruta usando «Ruta entre puntos» para obtenerla. + Espera el recálculo de la ruta. +\nEl gráfico estará disponible después del recálculo. + %1$s — %2$s + Viaje + Transporte + Símbolos + Deporte + Especial + Servicio + Emergencia + Comodidad + El archivo ya fue importado en OsmAnd \ No newline at end of file From 9b4282ca91c42526ec1d33392e845089c7d3c887 Mon Sep 17 00:00:00 2001 From: Franco Date: Sun, 1 Nov 2020 12:56:00 +0000 Subject: [PATCH 055/106] Translated using Weblate (Spanish (American)) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-es-rUS/phrases.xml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/values-es-rUS/phrases.xml b/OsmAnd/res/values-es-rUS/phrases.xml index 8c0dbc2414..89b147ca4a 100644 --- a/OsmAnd/res/values-es-rUS/phrases.xml +++ b/OsmAnd/res/values-es-rUS/phrases.xml @@ -3568,8 +3568,8 @@ Radioterapia Advertencia de peligro Categoría de dificultad - н/к (sin categoría) - н/к* (sin categoría, posible peligro) + s/c (sin categoría) + s/c* (sin categoría, posible peligro) 1A 1A* 1B @@ -3807,7 +3807,7 @@ Tipo de cabina No - Señal para encontrar el poste + Conexión a Internet: clientes Sólo se permite al caminar Contrastado Primitivo @@ -3852,4 +3852,9 @@ Frutos secos Panal de abejas Gas natural licuado + Torre de radar + Cobertizos + Azotea + Apartadero + Punto GPX \ No newline at end of file From b8c3af86b7a07e119c41af81c63226b3def90377 Mon Sep 17 00:00:00 2001 From: Verdulo Date: Mon, 2 Nov 2020 12:12:39 +0000 Subject: [PATCH 056/106] Translated using Weblate (Esperanto) Currently translated at 99.9% (3522 of 3524 strings) --- OsmAnd/res/values-eo/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index 9e3cd983c5..93ff65c8f2 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -3943,4 +3943,7 @@ Sporto Vivsavo Vojaĝo + MGRS + MGRS + OsmAnd uzas MGRS, kiu estas simila al la formo UTM NATO. \ No newline at end of file From a10b1d9a6ca809e87e7c51cf8990e39c2599b6a1 Mon Sep 17 00:00:00 2001 From: Verdulo Date: Mon, 2 Nov 2020 12:13:30 +0000 Subject: [PATCH 057/106] Translated using Weblate (Esperanto) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-eo/phrases.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-eo/phrases.xml b/OsmAnd/res/values-eo/phrases.xml index 2eae52044b..d1757bea9d 100644 --- a/OsmAnd/res/values-eo/phrases.xml +++ b/OsmAnd/res/values-eo/phrases.xml @@ -3842,4 +3842,5 @@ privataj garaĝ-budoj tegmento GPX-punkto + Radar-turo \ No newline at end of file From 5deb0edfada15ba9589d6b2c58abcd4481ee2fb2 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Sun, 1 Nov 2020 03:33:22 +0000 Subject: [PATCH 058/106] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (3524 of 3524 strings) --- OsmAnd/res/values-zh-rTW/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml index 980ed0c113..9e00acd9a5 100644 --- a/OsmAnd/res/values-zh-rTW/strings.xml +++ b/OsmAnd/res/values-zh-rTW/strings.xml @@ -3939,4 +3939,7 @@ 運動 警急 旅行 + MGRS + MGRS + OsmAnd 使用 MGRS,其類似於 UTM NATO 格式。 \ No newline at end of file From b0d3ebbae7b21af85cb1d927d34f4f8b9911da8b Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Sun, 1 Nov 2020 03:34:45 +0000 Subject: [PATCH 059/106] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-zh-rTW/phrases.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-zh-rTW/phrases.xml b/OsmAnd/res/values-zh-rTW/phrases.xml index 10415b42a8..8244b4067d 100644 --- a/OsmAnd/res/values-zh-rTW/phrases.xml +++ b/OsmAnd/res/values-zh-rTW/phrases.xml @@ -3848,4 +3848,5 @@ 車棚 屋頂 GPX 點 + 雷達塔 \ No newline at end of file From 243195757f4f7931bb6d0f159bba92d7b47a6594 Mon Sep 17 00:00:00 2001 From: Roger Pueyo Centelles Date: Mon, 2 Nov 2020 13:50:37 +0000 Subject: [PATCH 060/106] Translated using Weblate (Catalan) Currently translated at 97.3% (3429 of 3524 strings) --- OsmAnd/res/values-ca/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-ca/strings.xml b/OsmAnd/res/values-ca/strings.xml index 17ed9cdcb9..3ffb255368 100644 --- a/OsmAnd/res/values-ca/strings.xml +++ b/OsmAnd/res/values-ca/strings.xml @@ -3879,4 +3879,5 @@ Abasta l\'àrea: %1$s x %2$s Símbols Esport Emergència + Desenvoulpament nadiu de Transport Public \ No newline at end of file From f3c4b5936282fc33aa42f17decc208e2dab328b4 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Mon, 2 Nov 2020 16:22:49 +0200 Subject: [PATCH 061/106] Fix & refactoring --- .../main/java/net/osmand/IndexConstants.java | 2 +- .../plus/download/DownloadIndexesThread.java | 6 +- .../download/DownloadOsmandIndexesHelper.java | 13 ++-- .../helpers/FileNameTranslationHelper.java | 4 +- .../plus/resources/ResourceManager.java | 7 ++- .../plus/settings/backend/OsmandSettings.java | 2 +- .../backend/backup/DataSettingsItem.java | 2 +- .../backend/backup/FavoritesSettingsItem.java | 3 +- .../backend/backup/FileSettingsItem.java | 40 +++++++++++-- .../backup/OsmandSettingsItemReader.java | 3 +- .../backend/backup/SettingsExporter.java | 35 +---------- .../backend/backup/SettingsHelper.java | 59 ++++++++----------- .../backend/backup/SettingsImporter.java | 3 +- .../settings/backend/backup/SettingsItem.java | 2 +- .../backend/backup/SettingsItemReader.java | 12 +--- .../backend/backup/SettingsItemWriter.java | 9 +++ .../ExportImportSettingsAdapter.java | 12 ++-- .../fragments/ExportProfileBottomSheet.java | 2 +- .../ImportedSettingsItemsAdapter.java | 4 +- .../voice/AbstractPrologCommandPlayer.java | 3 +- .../plus/voice/JSTTSCommandPlayerImpl.java | 4 +- 21 files changed, 110 insertions(+), 117 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/IndexConstants.java b/OsmAnd-java/src/main/java/net/osmand/IndexConstants.java index 31ac655f06..3e4cd5af55 100644 --- a/OsmAnd-java/src/main/java/net/osmand/IndexConstants.java +++ b/OsmAnd-java/src/main/java/net/osmand/IndexConstants.java @@ -78,5 +78,5 @@ public class IndexConstants { public static final String ROUTING_PROFILES_DIR = "routing/"; public static final String PLUGINS_DIR = "plugins/"; - public static final String TTS_DIR_SUFFIX = "-tts"; + public static final String VOICE_PROVIDER_SUFFIX = "-tts"; } diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java b/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java index 7e0aadfa3b..3355d67a32 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java @@ -138,10 +138,10 @@ public class DownloadIndexesThread { String setTts = null; for (String s : OsmandSettings.TTS_AVAILABLE_VOICES) { if (lng.startsWith(s)) { - setTts = s + "-tts"; + setTts = s + IndexConstants.VOICE_PROVIDER_SUFFIX; break; } else if (lng.contains("," + s)) { - setTts = s + "-tts"; + setTts = s + IndexConstants.VOICE_PROVIDER_SUFFIX; } } if (setTts != null) { @@ -544,7 +544,7 @@ public class DownloadIndexesThread { // validate enough space if (asz != -1 && cs > asz) { String breakDownloadMessage = app.getString(R.string.download_files_not_enough_space, - cs, asz); + String.valueOf(cs), String.valueOf(asz)); publishProgress(breakDownloadMessage); return false; } diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadOsmandIndexesHelper.java b/OsmAnd/src/net/osmand/plus/download/DownloadOsmandIndexesHelper.java index 47b3015d56..f6381b3552 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadOsmandIndexesHelper.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadOsmandIndexesHelper.java @@ -8,9 +8,7 @@ import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.zip.GZIPInputStream; import net.osmand.AndroidUtils; @@ -159,10 +157,13 @@ public class DownloadOsmandIndexesHelper { List mapping = getBundledAssets(amanager); for (AssetEntry asset : mapping) { String target = asset.destination; - if (target.endsWith(IndexConstants.TTSVOICE_INDEX_EXT_JS) && target.startsWith("voice/") && target.contains("-tts")) { - String lang = target.substring("voice/".length(), target.indexOf("-tts")); - File destFile = new File(voicePath, target.substring("voice/".length(), - target.indexOf("/", "voice/".length())) + "/" + lang + "_tts.js"); + if (target.endsWith(IndexConstants.TTSVOICE_INDEX_EXT_JS) + && target.startsWith(IndexConstants.VOICE_INDEX_DIR) + && target.contains(IndexConstants.VOICE_PROVIDER_SUFFIX)) { + String lang = target.substring(IndexConstants.VOICE_INDEX_DIR.length(), + target.indexOf(IndexConstants.VOICE_PROVIDER_SUFFIX)); + File destFile = new File(voicePath, target.substring(IndexConstants.VOICE_INDEX_DIR.length(), + target.indexOf("/", IndexConstants.VOICE_INDEX_DIR.length())) + "/" + lang + "_tts.js"); result.add(new AssetIndexItem(lang + "_" + IndexConstants.TTSVOICE_INDEX_EXT_JS, "voice", date, dateModified, "0.1", destFile.length(), asset.source, destFile.getPath(), DownloadActivityType.VOICE_FILE)); diff --git a/OsmAnd/src/net/osmand/plus/helpers/FileNameTranslationHelper.java b/OsmAnd/src/net/osmand/plus/helpers/FileNameTranslationHelper.java index 539eceb622..229003050e 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/FileNameTranslationHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/FileNameTranslationHelper.java @@ -85,10 +85,10 @@ public class FileNameTranslationHelper { public static String getVoiceName(Context ctx, String fileName) { try { String nm = fileName.replace('-', '_').replace(' ', '_'); - if (nm.endsWith("_tts") || nm.endsWith("-tts")) { + if (nm.endsWith("_tts") || nm.endsWith(IndexConstants.VOICE_PROVIDER_SUFFIX)) { nm = nm.substring(0, nm.length() - 4); } - Field f = R.string.class.getField("lang_"+nm); + Field f = R.string.class.getField("lang_" + nm); if (f != null) { Integer in = (Integer) f.get(null); return ctx.getString(in); diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index ae123b2c8b..a87d5004bd 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -413,7 +413,7 @@ public class ResourceManager { java.text.DateFormat dateFormat = getDateFormat(); for (File f : lf) { if (f.isDirectory()) { - String lang = f.getName().replace("-tts", ""); + String lang = f.getName().replace(IndexConstants.VOICE_PROVIDER_SUFFIX, ""); File conf = new File(f, lang + "_" + IndexConstants.TTSVOICE_INDEX_EXT_JS); if (!conf.exists()) { conf = new File(f, "_config.p"); @@ -454,9 +454,10 @@ public class ResourceManager { if (appPath.canWrite()) { for (AssetEntry asset : assets) { File jsFile = new File(appPath, asset.destination); - if (asset.destination.contains("-tts") && asset.destination + if (asset.destination.contains(IndexConstants.VOICE_PROVIDER_SUFFIX) && asset.destination .endsWith(IndexConstants.TTSVOICE_INDEX_EXT_JS)) { - File oggFile = new File(appPath, asset.destination.replace("-tts", "")); + File oggFile = new File(appPath, asset.destination.replace( + IndexConstants.VOICE_PROVIDER_SUFFIX, "")); if (oggFile.getParentFile().exists() && !oggFile.exists()) { copyAssets(context.getAssets(), asset.source, oggFile); } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index 4c91964f0d..bcc7a4c170 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -2543,7 +2543,7 @@ public class OsmandSettings { Configuration config = ctx.getResources().getConfiguration(); for (String lang : TTS_AVAILABLE_VOICES) { if (lang.equals(config.locale.getLanguage())) { - return lang + "-tts"; + return lang + IndexConstants.VOICE_PROVIDER_SUFFIX; } } return "en-tts"; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/DataSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/DataSettingsItem.java index d68325fe5f..75529aa543 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/DataSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/DataSettingsItem.java @@ -64,7 +64,7 @@ public class DataSettingsItem extends StreamSettingsItem { SettingsItemReader getReader() { return new StreamSettingsItemReader(this) { @Override - public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, File destination) throws IOException, IllegalArgumentException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[SettingsHelper.BUFFER]; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FavoritesSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FavoritesSettingsItem.java index 8e8c4c6f36..a035ae0146 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FavoritesSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FavoritesSettingsItem.java @@ -16,6 +16,7 @@ import net.osmand.plus.R; import org.json.JSONException; import org.json.JSONObject; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -145,7 +146,7 @@ public class FavoritesSettingsItem extends CollectionSettingsItem return new SettingsItemReader(this) { @Override - public void readFromStream(@NonNull InputStream inputStream) throws IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, File destination) throws IllegalArgumentException { GPXFile gpxFile = GPXUtilities.loadGPXFile(inputStream); if (gpxFile.error != null) { warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType()))); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index 4ea7265310..3b4f8568e1 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -18,6 +18,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.zip.ZipOutputStream; public class FileSettingsItem extends StreamSettingsItem { @@ -100,7 +101,7 @@ public class FileSettingsItem extends StreamSettingsItem { } break; case TTS_VOICE: - if (name.startsWith(subtype.subtypeFolder) && name.endsWith(IndexConstants.TTS_DIR_SUFFIX)) { + if (name.startsWith(subtype.subtypeFolder) && name.endsWith(IndexConstants.VOICE_PROVIDER_SUFFIX)) { return subtype; } break; @@ -244,9 +245,8 @@ public class FileSettingsItem extends StreamSettingsItem { SettingsItemReader getReader() { return new StreamSettingsItemReader(this) { @Override - public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, File dest) throws IOException, IllegalArgumentException { OutputStream output; - File dest = getDestination(); if (dest.exists() && !shouldReplace) { dest = renameFile(dest); } @@ -279,6 +279,38 @@ public class FileSettingsItem extends StreamSettingsItem { 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); } - return super.getWriter(); + return new StreamSettingsItemWriter(this) { + + @Override + public void writeEntry(String fileName, @NonNull ZipOutputStream zos) throws IOException { + if (getSubtype().isDirectory()) { + File file = getFile(); + zipDirsWithFiles(file, zos); + } else { + super.writeEntry(fileName, zos); + } + } + + public void zipDirsWithFiles(File f, ZipOutputStream zos) + throws IOException { + if (f == null) { + return; + } + if (f.isDirectory()) { + File[] fs = f.listFiles(); + if (fs != null) { + for (File c : fs) { + zipDirsWithFiles(c, zos); + } + } + } else { + String zipEntryName = Algorithms.isEmpty(getSubtype().getSubtypeFolder()) + ? f.getName() + : f.getPath().substring(f.getPath().indexOf(getSubtype().getSubtypeFolder()) - 1); + setInputStream(new FileInputStream(f)); + super.writeEntry(zipEntryName, zos); + } + } + }; } } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/OsmandSettingsItemReader.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/OsmandSettingsItemReader.java index 0267e69471..df68e8a3e3 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/OsmandSettingsItemReader.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/OsmandSettingsItemReader.java @@ -10,6 +10,7 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -29,7 +30,7 @@ public abstract class OsmandSettingsItemReader ext @NonNull JSONObject json) throws JSONException; @Override - public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, File destination) throws IOException, IllegalArgumentException { StringBuilder buf = new StringBuilder(); try { BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java index 88b7851630..3a697b77c0 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java @@ -8,7 +8,6 @@ import org.json.JSONObject; import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -68,43 +67,11 @@ class SettingsExporter { if (Algorithms.isEmpty(fileName)) { fileName = item.getDefaultFileName(); } - if (item instanceof FileSettingsItem && ((FileSettingsItem) item).getSubtype().isDirectory()) { - File file = ((FileSettingsItem) item).getFile(); - zipDirsWithFiles(file, writer, zos); - } else { - ZipEntry entry = new ZipEntry(fileName); - zos.putNextEntry(entry); - writer.writeToStream(zos); - zos.closeEntry(); - } + writer.writeEntry(fileName, zos); } } } - public void zipDirsWithFiles(File f, SettingsItemWriter writer, ZipOutputStream zos) - throws IOException { - if (f == null) { - return; - } - if (f.isDirectory()) { - File[] fs = f.listFiles(); - if (fs != null) { - for (File c : fs) { - zipDirsWithFiles(c, writer, zos); - } - } - } else { - FileSettingsItem item = (FileSettingsItem) writer.getItem(); - String zipEntryName = Algorithms.isEmpty(item.getSubtype().getSubtypeFolder()) - ? f.getName() - : f.getPath().substring(f.getPath().indexOf(item.getSubtype().getSubtypeFolder()) - 1); - ZipEntry entry = new ZipEntry(zipEntryName); - zos.putNextEntry(entry); - item.setInputStream(new FileInputStream(f)); - writer.writeToStream(zos); - zos.closeEntry(); - } - } private JSONObject createItemsJson() throws JSONException { JSONObject json = new JSONObject(); 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 d198c81502..f3821505a2 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -533,20 +533,22 @@ public class SettingsHelper { dataList.put(ExportSettingsType.OSM_EDITS, editsPointList); } } - List files = getLocalMapFiles(); - if (!files.isEmpty()) { - dataList.put(ExportSettingsType.OFFLINE_MAPS, files); - } List favoriteGroups = app.getFavorites().getFavoriteGroups(); if (!favoriteGroups.isEmpty()) { dataList.put(ExportSettingsType.FAVORITES, favoriteGroups); } - List localVoiceFileList = getVoiceIndexInfo(); - files = getFilesByType(localVoiceFileList, LocalIndexType.TTS_VOICE_DATA); + List localIndexInfoList = getVoiceIndexInfo(); + List files; + files = getFilesByType(localIndexInfoList, LocalIndexType.MAP_DATA, LocalIndexType.TILES_DATA, + LocalIndexType.SRTM_DATA, LocalIndexType.WIKI_DATA); + if (!files.isEmpty()) { + dataList.put(ExportSettingsType.OFFLINE_MAPS, files); + } + files = getFilesByType(localIndexInfoList, LocalIndexType.TTS_VOICE_DATA); if (!files.isEmpty()) { dataList.put(ExportSettingsType.TTS_VOICE, files); } - files = getFilesByType(localVoiceFileList, LocalIndexType.VOICE_DATA); + files = getFilesByType(localIndexInfoList, LocalIndexType.VOICE_DATA); if (!files.isEmpty()) { dataList.put(ExportSettingsType.VOICE, files); } @@ -554,40 +556,25 @@ public class SettingsHelper { } private List getVoiceIndexInfo() { - LocalIndexHelper helper = new LocalIndexHelper(app); - List localVoiceInfoList = new ArrayList<>(); - helper.loadVoiceData(app.getAppPath(IndexConstants.VOICE_INDEX_DIR), localVoiceInfoList, false, - new AbstractLoadLocalIndexTask() { - @Override - public void loadFile(LocalIndexInfo... loaded) { - } - }); - return localVoiceInfoList; - } - - private List getFilesByType(List localVoiceFileList, LocalIndexType localIndexType) { - List files = new ArrayList<>(); - for (LocalIndexInfo map : localVoiceFileList) { - File file = new File(map.getPathToData()); - if (file.exists() && map.getType() == localIndexType) { - files.add(file); - } - } - return files; - } - - private List getLocalMapFiles() { - List files = new ArrayList<>(); - LocalIndexHelper helper = new LocalIndexHelper(app); - List localMapFileList = helper.getLocalIndexData(new AbstractLoadLocalIndexTask() { + return new LocalIndexHelper(app).getLocalIndexData(new AbstractLoadLocalIndexTask() { @Override public void loadFile(LocalIndexInfo... loaded) { } }); - for (LocalIndexInfo map : localMapFileList) { + } + + private List getFilesByType(List localVoiceFileList, LocalIndexType... localIndexType) { + List files = new ArrayList<>(); + for (LocalIndexInfo map : localVoiceFileList) { File file = new File(map.getPathToData()); - if (file.exists() && map.getType() != LocalIndexType.TTS_VOICE_DATA - && map.getType() != LocalIndexType.VOICE_DATA) { + boolean filtered = false; + for (LocalIndexType type : localIndexType) { + if (map.getType() == type) { + filtered = true; + break; + } + } + if (file.exists() && filtered) { files.add(file); } } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java index f1a6f2d894..fcc1fba2f7 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java @@ -124,8 +124,7 @@ class SettingsImporter { try { SettingsItemReader reader = item.getReader(); if (reader != null) { - reader.setDestination(app.getAppPath(fileName)); - reader.readFromStream(ois); + reader.readFromStream(ois, app.getAppPath(fileName)); } } catch (IllegalArgumentException e) { item.warnings.add(app.getString(R.string.settings_item_read_error, item.getName())); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java index 75c5ba6500..815710b94c 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java @@ -169,7 +169,7 @@ public abstract class SettingsItem { SettingsItemReader getJsonReader() { return new SettingsItemReader(this) { @Override - public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, File destination) throws IOException, IllegalArgumentException { StringBuilder buf = new StringBuilder(); try { BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java index 5269150adc..2e38e04f08 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java @@ -10,19 +10,9 @@ public abstract class SettingsItemReader { private T item; - File destination; - public SettingsItemReader(@NonNull T item) { this.item = item; } - public void setDestination(File destination) { - this.destination = destination; - } - - public File getDestination() { - return destination; - } - - public abstract void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException; + public abstract void readFromStream(@NonNull InputStream inputStream, File destination) throws IOException, IllegalArgumentException; } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemWriter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemWriter.java index 9e3cf61377..090767a493 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemWriter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemWriter.java @@ -4,6 +4,8 @@ import androidx.annotation.NonNull; import java.io.IOException; import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; public abstract class SettingsItemWriter { @@ -18,4 +20,11 @@ public abstract class SettingsItemWriter { } public abstract boolean writeToStream(@NonNull OutputStream outputStream) throws IOException; + + public void writeEntry(String fileName, @NonNull ZipOutputStream zos) throws IOException { + ZipEntry entry = new ZipEntry(fileName); + zos.putNextEntry(entry); + writeToStream(zos); + zos.closeEntry(); + } } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java index 01391b89e6..6affe49e6d 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java @@ -368,8 +368,12 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { for (Object item : listItems) { if (data.contains(item)) { amount++; - if (type == OFFLINE_MAPS && item instanceof FileSettingsItem) { - amountSize += ((FileSettingsItem) item).getSize(); + if (type == OFFLINE_MAPS) { + if (item instanceof FileSettingsItem) { + amountSize += ((FileSettingsItem) item).getSize(); + } else { + amountSize += ((File) item).length(); + } } } } @@ -403,9 +407,9 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { case OSM_NOTES: return R.string.osm_notes; case OSM_EDITS: - return R.string.osm_edit_modified_poi; + return R.string.osm_edits; case OFFLINE_MAPS: - return R.string.shared_string_local_maps; + return R.string.shared_string_maps; case FAVORITES: return R.string.shared_string_favorites; case TTS_VOICE: diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java index 4c86a45a85..0d621b6b50 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java @@ -295,7 +295,7 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { progress.dismiss(); } progress = new ProgressDialog(context); - progress.setTitle(app.getString(R.string.export_profile)); + progress.setTitle(app.getString(R.string.shared_string_export)); progress.setMessage(app.getString(R.string.shared_string_preparing)); progress.setCancelable(false); progress.show(); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportedSettingsItemsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportedSettingsItemsAdapter.java index 1c30923de4..3eec01930b 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportedSettingsItemsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportedSettingsItemsAdapter.java @@ -120,7 +120,7 @@ public class ImportedSettingsItemsAdapter extends break; case OSM_EDITS: holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_info_dark, activeColorRes)); - holder.title.setText(R.string.osm_edit_modified_poi); + holder.title.setText(R.string.osm_edits); break; case FAVORITES: holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_favorite, activeColorRes)); @@ -128,7 +128,7 @@ public class ImportedSettingsItemsAdapter extends break; case OFFLINE_MAPS: holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_map, activeColorRes)); - holder.title.setText(R.string.shared_string_local_maps); + holder.title.setText(R.string.shared_string_maps); break; case TTS_VOICE: holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_volume_up, activeColorRes)); diff --git a/OsmAnd/src/net/osmand/plus/voice/AbstractPrologCommandPlayer.java b/OsmAnd/src/net/osmand/plus/voice/AbstractPrologCommandPlayer.java index 44f301945f..fe17c52ab5 100644 --- a/OsmAnd/src/net/osmand/plus/voice/AbstractPrologCommandPlayer.java +++ b/OsmAnd/src/net/osmand/plus/voice/AbstractPrologCommandPlayer.java @@ -95,7 +95,8 @@ public abstract class AbstractPrologCommandPlayer implements CommandPlayer, Stat language = ((Struct) langVal).getName(); } } else { - language = voiceProvider.replace("-tts", "").replace("-formal", ""); + language = voiceProvider.replace(IndexConstants.VOICE_PROVIDER_SUFFIX, "") + .replace("-formal", ""); } } diff --git a/OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java b/OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java index e0c0018605..bf8d9803bf 100644 --- a/OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java +++ b/OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java @@ -28,8 +28,8 @@ public class JSTTSCommandPlayerImpl extends TTSCommandPlayerImpl { jsScope = context.initSafeStandardObjects(); try { BufferedReader br = new BufferedReader(new FileReader(new File( - app.getAppPath(IndexConstants.VOICE_INDEX_DIR).getAbsolutePath() + - "/" + voiceProvider + "/" + voiceProvider.replace("-tts", "_tts") + ".js"))); + app.getAppPath(IndexConstants.VOICE_INDEX_DIR).getAbsolutePath() + "/" + voiceProvider + "/" + + voiceProvider.replace(IndexConstants.VOICE_PROVIDER_SUFFIX, "_tts") + ".js"))); context.evaluateReader(jsScope, br, "JS", 1, null); br.close(); } catch (Exception e) { From f3900ffd4ac8fffe1b06efd5d393101b261bccec Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Mon, 2 Nov 2020 21:59:42 +0200 Subject: [PATCH 062/106] Fix hillshade, slope localization, map sorting --- .../plus/download/DownloadActivityType.java | 8 ++++---- .../helpers/FileNameTranslationHelper.java | 20 +++++++++++++------ .../backend/backup/SettingsHelper.java | 20 +++++++++++++++++++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadActivityType.java b/OsmAnd/src/net/osmand/plus/download/DownloadActivityType.java index 95631c9c8c..b516d73d2c 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadActivityType.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadActivityType.java @@ -342,7 +342,7 @@ public class DownloadActivityType { return FileNameTranslationHelper.getFontName(ctx, getBasename(indexItem)); } final String basename = getBasename(indexItem); - if (basename.endsWith(FileNameTranslationHelper.WIKI_NAME)){ + if (basename.endsWith(FileNameTranslationHelper.WIKI_NAME)) { return FileNameTranslationHelper.getWikiName(ctx, basename); } // if (this == HILLSHADE_FILE){ @@ -357,7 +357,7 @@ public class DownloadActivityType { final int ind = basename.indexOf("addresses-nationwide"); String downloadName = basename.substring(0, ind - 1) + basename.substring(ind + "addresses-nationwide".length()); return osmandRegions.getLocaleName(downloadName, includingParent) + - " "+ ctx.getString(R.string.index_item_nation_addresses); + " " + ctx.getString(R.string.index_item_nation_addresses); } else if (basename.startsWith("Depth_")) { final int extInd = basename.indexOf("osmand_ext"); String downloadName = extInd == -1 ? basename.substring(6, basename.length()).replace('_', ' ') @@ -438,11 +438,11 @@ public class DownloadActivityType { } if (this == HILLSHADE_FILE) { return fileName.substring(0, fileName.length() - IndexConstants.SQLITE_EXT.length()) - .replace(FileNameTranslationHelper.HILL_SHADE, ""); + .replace(FileNameTranslationHelper.HILL_SHADE + "_", ""); } if (this == SLOPE_FILE) { return fileName.substring(0, fileName.length() - IndexConstants.SQLITE_EXT.length()) - .replace(FileNameTranslationHelper.SLOPE, ""); + .replace(FileNameTranslationHelper.SLOPE + "_", ""); } if (fileName.endsWith(IndexConstants.SQLITE_EXT)) { return fileName.substring(0, fileName.length() - IndexConstants.SQLITE_EXT.length()); diff --git a/OsmAnd/src/net/osmand/plus/helpers/FileNameTranslationHelper.java b/OsmAnd/src/net/osmand/plus/helpers/FileNameTranslationHelper.java index 229003050e..e366d1e8bb 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/FileNameTranslationHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/FileNameTranslationHelper.java @@ -4,6 +4,7 @@ import android.content.Context; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.map.OsmandRegions; +import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.download.DownloadResources; @@ -18,10 +19,14 @@ import java.lang.reflect.Field; public class FileNameTranslationHelper { private static final Log LOG = PlatformUtil.getLog(FileNameTranslationHelper.class); public static final String WIKI_NAME = "_wiki"; - public static final String HILL_SHADE = "Hillshade_"; - public static final String SLOPE = "Slope_"; + public static final String HILL_SHADE = "Hillshade"; + public static final String SLOPE = "Slope"; public static final String SEA_DEPTH = "Depth_"; + public static String getFileNameWithRegion(OsmandApplication app, String fileName) { + return getFileName(app, app.getResourceManager().getOsmandRegions(), fileName); + } + public static String getFileName(Context ctx, OsmandRegions regions, String fileName) { String basename = getBasename(fileName); if (basename.endsWith(WIKI_NAME)) { //wiki files @@ -30,13 +35,15 @@ public class FileNameTranslationHelper { return getVoiceName(ctx, fileName); } else if (fileName.endsWith(IndexConstants.FONT_INDEX_EXT)) { //otf files return getFontName(ctx, basename); - } else if (fileName.startsWith(HILL_SHADE)){ + } else if (fileName.startsWith(HILL_SHADE)) { + basename = basename.replace(HILL_SHADE + " ", ""); return getTerrainName(ctx, regions, basename, R.string.download_hillshade_maps); } else if (fileName.startsWith(SLOPE)) { + basename = basename.replace(SLOPE + " ", ""); return getTerrainName(ctx, regions, basename, R.string.download_slope_maps); } else if (fileName.length() == 2) { //voice recorded files try { - Field f = R.string.class.getField("lang_"+fileName); + Field f = R.string.class.getField("lang_" + fileName); if (f != null) { Integer in = (Integer) f.get(null); return ctx.getString(in); @@ -62,9 +69,10 @@ public class FileNameTranslationHelper { public static String getTerrainName(Context ctx, OsmandRegions regions, String basename, int terrainNameRes) { - String terrain = ctx.getString(terrainNameRes) + " "; + basename = basename.replace(" ", "_"); + String terrain = ctx.getString(terrainNameRes); String locName = regions.getLocaleName(basename.trim(), true); - return terrain + locName; + return ctx.getString(R.string.ltr_or_rtl_combine_via_space, locName, "(" + terrain + ")"); } public static String getWikiName(Context ctx, String basename){ 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 f3821505a2..f6cbdb4b43 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -7,7 +7,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import net.osmand.AndroidUtils; +import net.osmand.Collator; import net.osmand.IndexConstants; +import net.osmand.OsmAndCollator; import net.osmand.PlatformUtil; import net.osmand.data.LatLon; import net.osmand.map.ITileSource; @@ -23,6 +25,7 @@ import net.osmand.plus.audionotes.AudioVideoNotesPlugin; import net.osmand.plus.audionotes.AudioVideoNotesPlugin.Recording; import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask; 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.osmedit.OpenstreetmapPoint; @@ -42,6 +45,8 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -542,6 +547,7 @@ public class SettingsHelper { files = getFilesByType(localIndexInfoList, LocalIndexType.MAP_DATA, LocalIndexType.TILES_DATA, LocalIndexType.SRTM_DATA, LocalIndexType.WIKI_DATA); if (!files.isEmpty()) { + sortData(files); dataList.put(ExportSettingsType.OFFLINE_MAPS, files); } files = getFilesByType(localIndexInfoList, LocalIndexType.TTS_VOICE_DATA); @@ -801,4 +807,18 @@ public class SettingsHelper { } return settingsToOperate; } + + public void sortData(List files) { + final Collator collator = OsmAndCollator.primaryCollator(); + Collections.sort(files, new Comparator() { + @Override + public int compare(File lhs, File rhs) { + return collator.compare(getNameToDisplay(lhs), getNameToDisplay(rhs)); + } + + private String getNameToDisplay(File item) { + return FileNameTranslationHelper.getFileNameWithRegion(app, item.getName()); + } + }); + } } \ No newline at end of file From 38ebaccc288f3ee08bc84ef809b4740fe0ed2153 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Tue, 3 Nov 2020 11:30:53 +0200 Subject: [PATCH 063/106] fix "Plan Route: Graphs" bugs and refactoring --- .../fragment_measurement_tool_graph.xml | 122 ++++++++------ .../net/osmand/plus/helpers/GpxUiHelper.java | 108 ++++++++---- .../plus/measurementtool/GraphsCard.java | 157 ++++++++++-------- .../graph/BaseGraphAdapter.java | 34 ++-- .../graph/CommonGraphAdapter.java | 40 ++--- .../graph/CustomGraphAdapter.java | 31 ++-- .../plus/myplaces/TrackSegmentFragment.java | 5 +- .../RouteDetailsFragment.java | 9 +- .../cards/RouteInfoCard.java | 1 + .../cards/RouteStatisticCard.java | 3 +- 10 files changed, 289 insertions(+), 221 deletions(-) diff --git a/OsmAnd/res/layout/fragment_measurement_tool_graph.xml b/OsmAnd/res/layout/fragment_measurement_tool_graph.xml index 45f0b484d5..555c1b6928 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool_graph.xml +++ b/OsmAnd/res/layout/fragment_measurement_tool_graph.xml @@ -26,9 +26,9 @@ android:id="@+id/common_graphs_container" android:layout_width="match_parent" android:layout_height="wrap_content" + android:orientation="vertical" android:visibility="gone" - tools:visibility="visible" - android:orientation="vertical"> + tools:visibility="visible"> + tools:visibility="visible"> + android:background="?attr/list_divider" /> - - - - + tools:visibility="visible"> + android:layout_marginStart="@dimen/content_padding" + android:layout_marginLeft="@dimen/content_padding" + android:layout_marginTop="@dimen/content_padding_small" + android:layout_marginEnd="@dimen/content_padding" + android:layout_marginRight="@dimen/content_padding" + android:orientation="horizontal"> - + + + + + + + + + + + + + + + @@ -134,8 +158,8 @@ android:id="@+id/btn_text" android:layout_width="match_parent" android:layout_height="0dp" - android:layout_weight="1" android:layout_gravity="start|center_vertical" + android:layout_weight="1" android:gravity="start|center_vertical" android:lineSpacingMultiplier="@dimen/bottom_sheet_text_spacing_multiplier" android:textColor="@color/preference_category_title" diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index edcf3dc07f..dd2a35a9a4 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -2057,47 +2057,85 @@ public class GpxUiHelper { OsmandApplication app, GPXTrackAnalysis analysis, boolean calcWithoutGaps, - LineGraphType... types) { + LineGraphType ... types) { if (app == null || chart == null || analysis == null || types == null) { - return Collections.emptyList(); + return new ArrayList<>(); } - List dataList = new ArrayList<>(); - for (LineGraphType type : types) { - switch (type) { - case ALTITUDE: { - if (analysis.hasElevationData) { - OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, false, true, calcWithoutGaps); - dataList.add(elevationDataSet); - } - break; + if (types.length > 1) { + return getDataSetsImpl(chart, app, analysis, calcWithoutGaps, types[0], types[1]); + } else { + return getDataSetsImpl(chart, app, analysis, calcWithoutGaps, types[0]); + } + } + + private static List getDataSetsImpl(@NonNull LineChart chart, + @NonNull OsmandApplication app, + @NonNull GPXTrackAnalysis analysis, + boolean calcWithoutGaps, + @NonNull LineGraphType type) { + List result = new ArrayList<>(); + ILineDataSet dataSet = getDataSet(chart, app, analysis, calcWithoutGaps, false, type); + if (dataSet != null) { + result.add(dataSet); + } + return result; + } + + private static List getDataSetsImpl(@NonNull LineChart chart, + @NonNull OsmandApplication app, + @NonNull GPXTrackAnalysis analysis, + boolean calcWithoutGaps, + @NonNull LineGraphType type1, + @NonNull LineGraphType type2) { + List result = new ArrayList<>(); + OrderedLineDataSet dataSet1 = getDataSet(chart, app, analysis, calcWithoutGaps, false, type1); + OrderedLineDataSet dataSet2 = getDataSet(chart, app, analysis, calcWithoutGaps, true, type2); + if (dataSet1 == null && dataSet2 == null) { + return new ArrayList<>(); + } else if (dataSet1 == null) { + result.add(dataSet2); + } else if (dataSet2 == null) { + result.add(dataSet1); + } else if (dataSet1.getPriority() < dataSet2.getPriority()) { + result.add(dataSet2); + result.add(dataSet1); + } else { + result.add(dataSet1); + result.add(dataSet2); + } + return result; + } + + private static OrderedLineDataSet getDataSet(@NonNull LineChart chart, + @NonNull OsmandApplication app, + @NonNull GPXTrackAnalysis analysis, + boolean calcWithoutGaps, + boolean useRightAxis, + @NonNull LineGraphType type) { + OrderedLineDataSet dataSet = null; + switch (type) { + case ALTITUDE: { + if (analysis.hasElevationData) { + dataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, useRightAxis, true, calcWithoutGaps); } - case SLOPE: - if (analysis.hasElevationData) { - OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, null, true, true, calcWithoutGaps); - dataList.add(slopeDataSet); - } - break; - case SPEED: { - if (analysis.hasSpeedData) { - OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, - analysis, GPXDataSetAxisType.DISTANCE, false, true, calcWithoutGaps); - dataList.add(speedDataSet); - } - break; + break; + } + case SLOPE: + if (analysis.hasElevationData) { + dataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, null, useRightAxis, true, calcWithoutGaps); } + break; + case SPEED: { + if (analysis.hasSpeedData) { + dataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, useRightAxis, true, calcWithoutGaps); + } + break; } } - if (dataList.size() > 0) { - Collections.sort(dataList, new Comparator() { - @Override - public int compare(OrderedLineDataSet o1, OrderedLineDataSet o2) { - return Float.compare(o1.getPriority(), o2.getPriority()); - } - }); - } - return new ArrayList(dataList); + return dataSet; } public static GpxDisplayItem makeGpxDisplayItem(OsmandApplication app, GPXUtilities.GPXFile gpx) { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java index a7f35b4d0a..69277f19a6 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java @@ -25,8 +25,6 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.LineGraphType; -import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; -import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; @@ -47,6 +45,9 @@ import java.util.List; import static net.osmand.GPXUtilities.GPXFile; import static net.osmand.GPXUtilities.GPXTrackAnalysis; +import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.ALTITUDE; +import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SLOPE; +import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SPEED; import static net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem; import static net.osmand.router.RouteStatisticsHelper.RouteStatistics; @@ -57,9 +58,9 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen private MeasurementEditingContext editingCtx; private MeasurementToolFragment fragment; - - private GraphType visibleType; - private List graphTypes = new ArrayList<>(); + private TrackDetailsMenu trackDetailsMenu; + private GPXFile gpxFile; + private GPXTrackAnalysis analysis; private GpxDisplayItem gpxItem; private View commonGraphContainer; @@ -69,24 +70,8 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen private CustomGraphAdapter customGraphAdapter; private RecyclerView graphTypesMenu; - private TrackDetailsMenu trackDetailsMenu; - - private enum CommonGraphType { - OVERVIEW(R.string.shared_string_overview, true, LineGraphType.ALTITUDE, LineGraphType.SLOPE), - ALTITUDE(R.string.altitude, true, LineGraphType.ALTITUDE), - SLOPE(R.string.shared_string_slope, true, LineGraphType.SLOPE), - SPEED(R.string.map_widget_speed, false, LineGraphType.SPEED); - - CommonGraphType(int titleId, boolean canBeCalculated, LineGraphType ... lineGraphTypes) { - this.titleId = titleId; - this.canBeCalculated = canBeCalculated; - this.lineGraphTypes = lineGraphTypes; - } - - final int titleId; - final boolean canBeCalculated; - final LineGraphType[] lineGraphTypes; - } + private GraphType visibleType; + private List graphTypes = new ArrayList<>(); public GraphsCard(@NonNull MapActivity mapActivity, TrackDetailsMenu trackDetailsMenu, @@ -137,23 +122,23 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen private void fullUpdate() { if (!isRouteCalculating()) { updateData(); - updateVisibleType(); - updateTypesMenu(); + setupVisibleType(); + updateMenu(); } - updateInfoView(); + updateView(); } - private void updateTypesMenu() { + private void updateMenu() { if (!editingCtx.isPointsEnoughToCalculateRoute()) { graphTypesMenu.setVisibility(View.GONE); } else { graphTypesMenu.setVisibility(View.VISIBLE); graphTypesMenu.removeAllViews(); - fillInTypesMenu(); + fillInMenu(); } } - private void fillInTypesMenu() { + private void fillInMenu() { OsmandApplication app = getMyApplication(); int activeColorId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; final HorizontalSelectionAdapter adapter = new HorizontalSelectionAdapter(app, nightMode); @@ -176,7 +161,7 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen adapter.setItems(items); adapter.setSelectedItem(item); GraphType chosenType = (GraphType) item.getObject(); - if (!isCurrentVisibleType(chosenType)) { + if (!isVisibleType(chosenType)) { changeVisibleType(chosenType); } } @@ -187,10 +172,10 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen private void changeVisibleType(GraphType type) { visibleType = type; - updateInfoView(); + updateView(); } - private boolean isCurrentVisibleType(GraphType type) { + private boolean isVisibleType(GraphType type) { if (visibleType != null && type != null) { return Algorithms.objectEquals(visibleType.getTitle(), type.getTitle()); } @@ -206,7 +191,7 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen return null; } - private void updateInfoView() { + private void updateView() { hideAll(); if (!editingCtx.isPointsEnoughToCalculateRoute()) { showMessage(app.getString(R.string.message_you_need_add_two_points_to_show_graphs)); @@ -279,54 +264,59 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen CustomGraphType customGraphType = (CustomGraphType) visibleType; customGraphContainer.setVisibility(View.VISIBLE); customGraphAdapter.setLegendViewType(LegendViewType.ONE_ELEMENT); - customGraphAdapter.fullUpdate((BarData) customGraphType.getGraphData(), customGraphType.getStatistics()); + customGraphAdapter.updateContent(customGraphType.getChartData(), customGraphType.getStatistics()); } else { + CommonGraphType commonGraphType = (CommonGraphType) visibleType; commonGraphContainer.setVisibility(View.VISIBLE); customGraphAdapter.setLegendViewType(LegendViewType.GONE); - commonGraphAdapter.fullUpdate((LineData) visibleType.getGraphData(), gpxItem); + commonGraphAdapter.updateContent(commonGraphType.getChartData(), gpxItem); } } private void updateData() { graphTypes.clear(); OsmandApplication app = getMyApplication(); - GPXFile gpxFile = getGpxFile(); - GPXTrackAnalysis analysis = gpxFile != null ? gpxFile.getAnalysis(0) : null; + gpxFile = getGpxFile(); + analysis = gpxFile != null ? gpxFile.getAnalysis(0) : null; gpxItem = gpxFile != null ? GpxUiHelper.makeGpxDisplayItem(app, gpxFile) : null; if (gpxItem != null) { trackDetailsMenu.setGpxItem(gpxItem); } + if (analysis == null) return; // update common graph data - for (CommonGraphType commonType : CommonGraphType.values()) { - List dataSets = GpxUiHelper.getDataSets(commonGraphAdapter.getChart(), - app, analysis, false, commonType.lineGraphTypes); - LineData data = !Algorithms.isEmpty(dataSets) ? new LineData(dataSets) : null; - String title = app.getString(commonType.titleId); - graphTypes.add(new GraphType(title, commonType.canBeCalculated, data)); - } + boolean hasElevationData = analysis.hasElevationData; + boolean hasSpeedData = analysis.isSpeedSpecified(); + addCommonType(R.string.shared_string_overview, true, hasElevationData, ALTITUDE, SLOPE); + addCommonType(R.string.altitude, true, hasElevationData, ALTITUDE); + addCommonType(R.string.shared_string_slope, true, hasElevationData, SLOPE); + addCommonType(R.string.map_widget_speed, false, hasSpeedData, SPEED); // update custom graph data List routeStatistics = calculateRouteStatistics(); if (analysis != null && routeStatistics != null) { for (RouteStatistics statistics : routeStatistics) { String title = AndroidUtils.getStringRouteInfoPropertyValue(app, statistics.name); - BarData data = null; - if (!Algorithms.isEmpty(statistics.elements)) { - data = GpxUiHelper.buildStatisticChart(app, customGraphAdapter.getChart(), - statistics, analysis, true, nightMode); - } - graphTypes.add(new CustomGraphType(title, false, data, statistics)); + graphTypes.add(new CustomGraphType(title, statistics)); } } } - private void updateVisibleType() { + private void addCommonType(int titleId, + boolean canBeCalculated, + boolean hasData, + LineGraphType ... lineGraphTypes) { + OsmandApplication app = getMyApplication(); + String title = app.getString(titleId); + graphTypes.add(new CommonGraphType(title, canBeCalculated, hasData, lineGraphTypes)); + } + + private void setupVisibleType() { if (visibleType == null) { visibleType = getFirstAvailableType(); } else { for (GraphType type : graphTypes) { - if (isCurrentVisibleType(type)) { + if (isVisibleType(type)) { visibleType = type.isAvailable() ? type : getFirstAvailableType(); break; } @@ -346,23 +336,23 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen private List calculateRouteStatistics() { OsmandApplication app = getMyApplication(); List route = editingCtx.getAllRouteSegments(); - if (route == null || app == null) return null; - return RouteDetailsFragment.calculateRouteStatistics(app, route, nightMode); + if (route != null && app != null) { + return RouteDetailsFragment.calculateRouteStatistics(app, route, nightMode); + } + return null; } private boolean isRouteCalculating() { return fragment.isProgressBarVisible(); } - private class GraphType { + private abstract class GraphType { private String title; private boolean canBeCalculated; - private ChartData graphData; - public GraphType(String title, boolean canBeCalculated, ChartData graphData) { + public GraphType(String title, boolean canBeCalculated) { this.title = title; this.canBeCalculated = canBeCalculated; - this.graphData = graphData; } public String getTitle() { @@ -385,26 +375,63 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen return canBeCalculated; } - public boolean hasData() { - return getGraphData() != null; + public abstract boolean hasData(); + + public abstract T getChartData(); + } + + private class CommonGraphType extends GraphType { + + private boolean hasData; + private LineGraphType[] lineGraphTypes; + + public CommonGraphType(String title, boolean canBeCalculated, boolean hasData, LineGraphType ... lineGraphTypes) { + super(title, canBeCalculated); + this.hasData = hasData; + this.lineGraphTypes = lineGraphTypes; } - public ChartData getGraphData() { - return graphData; + @Override + public boolean hasData() { + return hasData; + } + + @Override + public LineData getChartData() { + GpxUiHelper.setupGPXChart(commonGraphAdapter.getChart(), 4, 24f, 16f, !nightMode, true); + List dataSets = GpxUiHelper.getDataSets(commonGraphAdapter.getChart(), + app, analysis, false, lineGraphTypes); + return !Algorithms.isEmpty(dataSets) ? new LineData(dataSets) : null; } } - private class CustomGraphType extends GraphType { + private class CustomGraphType extends GraphType { private RouteStatistics statistics; - public CustomGraphType(String title, boolean canBeCalculated, ChartData graphData, RouteStatistics statistics) { - super(title, canBeCalculated, graphData); + public CustomGraphType(String title, RouteStatistics statistics) { + super(title, false); this.statistics = statistics; } public RouteStatistics getStatistics() { return statistics; } + + @Override + public boolean hasData() { + return !Algorithms.isEmpty(statistics.elements); + } + + @Override + public BarData getChartData() { + GpxUiHelper.setupHorizontalGPXChart(app, customGraphAdapter.getChart(), 5, 9, 24, true, nightMode); + BarData data = null; + if (!Algorithms.isEmpty(statistics.elements)) { + data = GpxUiHelper.buildStatisticChart(app, customGraphAdapter.getChart(), + statistics, analysis, true, nightMode); + } + return data; + } } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/BaseGraphAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/BaseGraphAdapter.java index dc83460a3f..5f9e1fdc29 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/graph/BaseGraphAdapter.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/BaseGraphAdapter.java @@ -10,27 +10,27 @@ import com.github.mikephil.charting.listener.ChartTouchListener; import net.osmand.plus.OsmandApplication; -public abstract class BaseGraphAdapter { +public abstract class BaseGraphAdapter<_Chart extends Chart, _ChartData extends ChartData, _Data> { private Highlight lastKnownHighlight; - protected CHART mChart; - protected CHART_DATA mChartData; - protected DATA mAdditionalData; + protected _Chart chart; + protected _ChartData chartData; + protected _Data additionalData; protected boolean usedOnMap; - public BaseGraphAdapter(CHART chart, boolean usedOnMap) { - this.mChart = chart; + public BaseGraphAdapter(_Chart chart, boolean usedOnMap) { + this.chart = chart; this.usedOnMap = usedOnMap; - prepareCharterView(); + prepareChartView(); } - protected void prepareCharterView() { - mChart.setExtraRightOffset(16); - mChart.setExtraLeftOffset(16); + protected void prepareChartView() { + chart.setExtraRightOffset(16); + chart.setExtraLeftOffset(16); } - public CHART getChart() { - return mChart; + public _Chart getChart() { + return chart; } protected void updateHighlight() { @@ -41,14 +41,14 @@ public abstract class BaseGraphAdapter 0) { - highlightDrawX = mChart.getHighlighted()[0].getDrawX(); + if (chart.getHighlighted() != null && chart.getHighlighted().length > 0) { + highlightDrawX = chart.getHighlighted()[0].getDrawX(); } else { highlightDrawX = -1; } @@ -68,8 +67,8 @@ public class CommonGraphAdapter extends BaseGraphAdapter 0) { gpxItem.chartHighlightPos = highlights[0].getX(); } else { @@ -104,17 +103,9 @@ public class CommonGraphAdapter extends BaseGraphAdapter 0) { - gpxItem = group.getModifiableList().get(0); - if (gpxItem != null) { - gpxItem.route = true; - } - } + gpxItem = GpxUiHelper.makeGpxDisplayItem(app, gpx); } void openDetails() { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java index c2cbec6f7b..124687f2f7 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java @@ -41,6 +41,7 @@ public class RouteInfoCard extends BaseCard { updateHeader(); LinearLayout container = (LinearLayout) view.findViewById(R.id.route_items); HorizontalBarChart chart = (HorizontalBarChart) view.findViewById(R.id.chart); + GpxUiHelper.setupHorizontalGPXChart(getMyApplication(), chart, 5, 9, 24, true, nightMode); BarData barData = GpxUiHelper.buildStatisticChart(app, chart, statistics, analysis, true, nightMode); graphAdapter = new CustomGraphAdapter(chart, true); graphAdapter.setLegendContainer(container); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java index bb6483155b..e25c242469 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java @@ -217,6 +217,7 @@ public class RouteStatisticCard extends BaseCard { private void buildHeader(GPXTrackAnalysis analysis) { LineChart mChart = (LineChart) view.findViewById(R.id.chart); + GpxUiHelper.setupGPXChart(mChart, 4, 24f, 16f, !nightMode, true); graphAdapter = new CommonGraphAdapter(mChart, true); if (analysis.hasElevationData) { @@ -235,7 +236,7 @@ public class RouteStatisticCard extends BaseCard { this.elevationDataSet = elevationDataSet; this.slopeDataSet = slopeDataSet; - graphAdapter.fullUpdate(new LineData(dataSets), gpxItem); + graphAdapter.updateContent(new LineData(dataSets), gpxItem); mChart.setVisibility(View.VISIBLE); } else { mChart.setVisibility(View.GONE); From 0fc38bfa371c32c765c69b22320f4a31c7cce790 Mon Sep 17 00:00:00 2001 From: Simon Legner Date: Tue, 3 Nov 2020 11:42:39 +0000 Subject: [PATCH 064/106] Translated using Weblate (German) Currently translated at 99.9% (3523 of 3524 strings) --- OsmAnd/res/values-de/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index 1a1693eee7..72b8274e30 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -3946,4 +3946,6 @@ Reisen Sport Notfall + Graph + Symbole \ No newline at end of file From c450fb243435503bdc2f57e1f04b5eaa529b5a46 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 3 Nov 2020 08:47:08 +0000 Subject: [PATCH 065/106] Translated using Weblate (German) Currently translated at 99.9% (3523 of 3524 strings) --- OsmAnd/res/values-de/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index 72b8274e30..ef1285f3f1 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -3940,7 +3940,7 @@ MGRS Warte auf die Neuberechnung der Route. \nDie Graphik wird nach der Neuberechnung verfügbar sein. - Ausstattung + Einrichtung ÖPNV Dienstleistung Reisen @@ -3948,4 +3948,6 @@ Notfall Graph Symbole + Lokale Karten + Spezial \ No newline at end of file From 1a92146c7179402fab4395d433247fe664913cb8 Mon Sep 17 00:00:00 2001 From: josep constanti Date: Mon, 2 Nov 2020 13:53:22 +0000 Subject: [PATCH 066/106] Translated using Weblate (Catalan) Currently translated at 97.3% (3430 of 3524 strings) --- OsmAnd/res/values-ca/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-ca/strings.xml b/OsmAnd/res/values-ca/strings.xml index 3ffb255368..04ad6f0150 100644 --- a/OsmAnd/res/values-ca/strings.xml +++ b/OsmAnd/res/values-ca/strings.xml @@ -3879,5 +3879,6 @@ Abasta l\'àrea: %1$s x %2$s Símbols Esport Emergència - Desenvoulpament nadiu de Transport Public + Desenvolupament local de Transport Public + Discontinu \ No newline at end of file From 4e307b59dc6b595819f97bee5b0ab8b15f082e6c Mon Sep 17 00:00:00 2001 From: ffff23 Date: Tue, 3 Nov 2020 05:15:30 +0000 Subject: [PATCH 067/106] Translated using Weblate (Japanese) Currently translated at 97.7% (3446 of 3524 strings) --- OsmAnd/res/values-ja/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd/res/values-ja/strings.xml b/OsmAnd/res/values-ja/strings.xml index ef429b88a7..ab453f2545 100644 --- a/OsmAnd/res/values-ja/strings.xml +++ b/OsmAnd/res/values-ja/strings.xml @@ -3809,8 +3809,8 @@ POIの更新は利用できません オンラインソースを追加 これらの変更を適用すると、このタイルソースのキャッシュデータがクリアされます 船の高さを設定 - 低い橋を避けるために船の高さを調整できます。ブリッジが可動式の場合は、開いた状態の高さが参照されます。 - 低い橋を避けるために船の高さを設定します。注:ブリッジが可動式の場合は、開いた状態の高さが参照されます。 + 低い橋を避けるために船の高さを調整できます。橋が可動式の場合は、開いた状態の高さが参照されます。 + 低い橋を避けるために船の高さを設定します。注:橋が可動式の場合は、開いた状態の高さが参照されます。 狭い橋を避けるために船の幅を設定します Mapillaryの表示切替 Mapillaryを非表示 From 61e9ffbc337bcbf6f299892c9521b3e007e2b64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Babos=20G=C3=A1bor?= Date: Mon, 2 Nov 2020 18:05:06 +0000 Subject: [PATCH 068/106] Translated using Weblate (Hungarian) Currently translated at 99.9% (3523 of 3524 strings) --- OsmAnd/res/values-hu/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-hu/strings.xml b/OsmAnd/res/values-hu/strings.xml index f3762a3fd1..5d656a709f 100644 --- a/OsmAnd/res/values-hu/strings.xml +++ b/OsmAnd/res/values-hu/strings.xml @@ -3935,4 +3935,7 @@ Sport Vészhelyzet Utazás + MGRS + MGRS + Az OsmAnd a NATO által is használt MGRS (Military Grid Reference System) koordinátákat alkamazza, amely hasonlít az UTM-formátumhoz. \ No newline at end of file From 8c319c7ab7d51a9c02ac655a557d953afc6f5a78 Mon Sep 17 00:00:00 2001 From: Mirco Zorzo Date: Mon, 2 Nov 2020 17:14:32 +0000 Subject: [PATCH 069/106] Translated using Weblate (Italian) Currently translated at 89.7% (3162 of 3524 strings) --- OsmAnd/res/values-it/strings.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml index e950feca34..db30024603 100644 --- a/OsmAnd/res/values-it/strings.xml +++ b/OsmAnd/res/values-it/strings.xml @@ -3933,4 +3933,16 @@ \nIl grafico sarà disponibile dopo il ricalcolo. %1$s — %2$s Buco + MGRS + MGRS + OsmAnd utilizza MGRS, che è simile al formato UTM NATO. + Mappe locali + Amenità + Speciale + Trasporto + Servizio + Simboli + Sport + Emergenza + Viaggio \ No newline at end of file From 7a45544c0addb21d3db0b08ce8b94846699c019b Mon Sep 17 00:00:00 2001 From: iman Date: Mon, 2 Nov 2020 20:42:37 +0000 Subject: [PATCH 070/106] Translated using Weblate (Persian) Currently translated at 99.3% (3500 of 3524 strings) --- OsmAnd/res/values-fa/strings.xml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/values-fa/strings.xml b/OsmAnd/res/values-fa/strings.xml index c7674bb67d..46a00d0720 100644 --- a/OsmAnd/res/values-fa/strings.xml +++ b/OsmAnd/res/values-fa/strings.xml @@ -3482,7 +3482,7 @@ ردهای ضبط‌شدهٔ شما در %1$s یا در پوشهٔ OsmAnd قرار دارند. یادداشت‌های OSMای شما در %1$s قرار دارند. ویرایش‌ها یا یادداشت‌های OSMای خود که هنوز بارگذاری نشده‌اند را در %1$s ببینید. نقاط بارگذاری‌شده را دیگر نمی‌بینید. - لاگ‌های جزئی برنامه را ببینید و هم‌رسانی کنید + لاگ‌های جزئی برنامه را بررسی و هم‌رسانی کنید استفاده از برنامهٔ سیستم صدای شاتر دوربین احراز هویت موفقیت‌آمیز بود @@ -3630,8 +3630,8 @@ زبان همهٔ زبان‌ها تعداد اقلام «کشو»، «پیکربندی نقشه» و «منوی زمینه» را به‌دلخواه تنظیم کنید. -\n -\nافزونه‌های بی‌استفاده را غیرفعال کنید تا همهٔ کنترل‌های آن‌ها از برنامه پنهان شود. +\n +\nافزونه‌های بی‌استفاده را غیرفعال کنید تا همهٔ کنترل‌های آن‌ها از برنامه پنهان شود. %1$s. پنهان‌سازی تنظیمات آن‌ها را به حالت اولیه بازنشانی می‌کند. این اقلام از منو پنهان می‌شوند، اما گزینه‌ها یا افزونه‌های متناظر همچنان کار می‌کنند. پنهان @@ -3942,4 +3942,12 @@ مسیریابی دومرحله‌ای برای ناوبری خودرویی. مسیریابی پیچیده برای مسیریابی حمل‌ونقل عمومی از محاسبات جاوا (امن) استفاده می‌کند + نقشه‌های محلی + ویژه + حمل‌ونقل + خدمات + نمادها + ورزش + اورژانس + سفر \ No newline at end of file From e0279bb76330d3c623074145746d0e758cdb4315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Kotr=C4=8D?= Date: Mon, 2 Nov 2020 20:45:46 +0000 Subject: [PATCH 071/106] Translated using Weblate (Czech) Currently translated at 80.7% (2844 of 3524 strings) --- OsmAnd/res/values-cs/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-cs/strings.xml b/OsmAnd/res/values-cs/strings.xml index 0fd23b4381..5c5a1a7d25 100644 --- a/OsmAnd/res/values-cs/strings.xml +++ b/OsmAnd/res/values-cs/strings.xml @@ -3651,4 +3651,7 @@ Zobrazená oblast: %1$s x %2$s Sport Nouzová situace Cestování + Nechat obrazovku zapnutou + Nechat obrazovku vypnutou + Dále, pro použití této možnosti připojte vaši stopu k nejbližší povolené cestě s některým z vašich navigačních profilů. \ No newline at end of file From ee9b28a63e8d22502c97dbf23b1404ee28c7d18c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=BB=D0=B0=D0=BC=D0=B5=D0=BD?= Date: Mon, 2 Nov 2020 16:13:58 +0000 Subject: [PATCH 072/106] Translated using Weblate (Bulgarian) Currently translated at 47.5% (1674 of 3524 strings) --- OsmAnd/res/values-bg/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OsmAnd/res/values-bg/strings.xml b/OsmAnd/res/values-bg/strings.xml index 2a02f5ee55..35f42cfdcc 100644 --- a/OsmAnd/res/values-bg/strings.xml +++ b/OsmAnd/res/values-bg/strings.xml @@ -2212,4 +2212,10 @@ Превключете на Java (безопасен режим) изчисляването на маршрути за обществения транспорт Влезте с OAuth, за да ползвате всички функции на osmedit Вход с OAuth + Системна настройка + Всички следващи сегменти + Предишен сегмент + Всички предишни сегменти + Само избраният сегмент ще бъде преизчислен съобразно избрания профил. + Всички следващи сегменти ще бъдат преизчислени с помощта на избрания профил. \ No newline at end of file From b46d409288e4be96846ed415bb1983e19e056305 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 3 Nov 2020 08:52:25 +0000 Subject: [PATCH 073/106] Translated using Weblate (German) Currently translated at 99.6% (3817 of 3830 strings) --- OsmAnd/res/values-de/phrases.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-de/phrases.xml b/OsmAnd/res/values-de/phrases.xml index 011706fbf0..4999a997a0 100644 --- a/OsmAnd/res/values-de/phrases.xml +++ b/OsmAnd/res/values-de/phrases.xml @@ -3852,4 +3852,5 @@ Überdachter Parkplatz Dachparkplätze GPX-Wegpunkt + Radarturm \ No newline at end of file From e535cd2b8efd1d1d672d0a86a8891389eca2fae2 Mon Sep 17 00:00:00 2001 From: ffff23 Date: Mon, 2 Nov 2020 15:29:51 +0000 Subject: [PATCH 074/106] Translated using Weblate (Japanese) Currently translated at 99.3% (3807 of 3830 strings) --- OsmAnd/res/values-ja/phrases.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd/res/values-ja/phrases.xml b/OsmAnd/res/values-ja/phrases.xml index 4dd597c4ae..c4199b91d4 100644 --- a/OsmAnd/res/values-ja/phrases.xml +++ b/OsmAnd/res/values-ja/phrases.xml @@ -361,7 +361,7 @@ 法律事務所 通信会社事務所 NGO・非政府組織 - 町役場・市庁舎 + 役場・庁舎 職業紹介所 研究所 IT関連事務所 @@ -370,7 +370,7 @@ 広告代理店 教育団体事務所 テレビ・ラジオ・録音スタジオ - 賭博場 + ブックメーカー スタジアム 総合スポーツ場 ゴルフ場 From d0e0703f706aed0343019b934dd99a0a86c6a34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Babos=20G=C3=A1bor?= Date: Mon, 2 Nov 2020 18:00:35 +0000 Subject: [PATCH 075/106] Translated using Weblate (Hungarian) Currently translated at 99.9% (3828 of 3830 strings) --- OsmAnd/res/values-hu/phrases.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OsmAnd/res/values-hu/phrases.xml b/OsmAnd/res/values-hu/phrases.xml index 99f11bb034..c20dc74cd4 100644 --- a/OsmAnd/res/values-hu/phrases.xml +++ b/OsmAnd/res/values-hu/phrases.xml @@ -3840,4 +3840,6 @@ Fedett parkolóhely Tető Internetcsatlakozás: ügyfeleknek + Radartorony + GPX-pont \ No newline at end of file From b4dcdf74b32c7d9ccaf25a789fa5aa67d6688c4e Mon Sep 17 00:00:00 2001 From: Eduardo Addad de Oliveira Date: Mon, 2 Nov 2020 19:51:34 +0000 Subject: [PATCH 076/106] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-pt-rBR/phrases.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsmAnd/res/values-pt-rBR/phrases.xml b/OsmAnd/res/values-pt-rBR/phrases.xml index 068381b014..f9bb017fe2 100644 --- a/OsmAnd/res/values-pt-rBR/phrases.xml +++ b/OsmAnd/res/values-pt-rBR/phrases.xml @@ -3847,4 +3847,7 @@ GNL Galpões Ponto GPX + Torre de radar + Tapume + Terraço \ No newline at end of file From 77aa5f0d64d96c8d7983ab4e566acaaa67a29f11 Mon Sep 17 00:00:00 2001 From: Mirco Zorzo Date: Tue, 3 Nov 2020 10:25:56 +0000 Subject: [PATCH 077/106] Translated using Weblate (Italian) Currently translated at 97.7% (265 of 271 strings) Translation: OsmAnd/Telegram Translate-URL: https://hosted.weblate.org/projects/osmand/telegram/it/ --- OsmAnd-telegram/res/values-it/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd-telegram/res/values-it/strings.xml b/OsmAnd-telegram/res/values-it/strings.xml index 04ca50389d..05cf56a8da 100644 --- a/OsmAnd-telegram/res/values-it/strings.xml +++ b/OsmAnd-telegram/res/values-it/strings.xml @@ -266,4 +266,5 @@ Ultimo aggiornamento da Telegram: %1$s ERR Controlla e condividi i log dettagliati dell\'applicazione + Logcat buffer \ No newline at end of file From 140f2c2e034b64af05f71d633022f4388f093e98 Mon Sep 17 00:00:00 2001 From: iman Date: Mon, 2 Nov 2020 20:40:09 +0000 Subject: [PATCH 078/106] Translated using Weblate (Persian) Currently translated at 30.2% (82 of 271 strings) Translation: OsmAnd/Telegram Translate-URL: https://hosted.weblate.org/projects/osmand/telegram/fa/ --- OsmAnd-telegram/res/values-fa/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OsmAnd-telegram/res/values-fa/strings.xml b/OsmAnd-telegram/res/values-fa/strings.xml index 13e67eef49..092218d713 100644 --- a/OsmAnd-telegram/res/values-fa/strings.xml +++ b/OsmAnd-telegram/res/values-fa/strings.xml @@ -78,4 +78,8 @@ آخرین پاسخ: %1$s آخرین به‌روزرسانی تلگرام: %1$s خطا + ارسال گزارش + برون‌برد + بافر لاگ‌کت + لاگ‌های جزئی برنامه را بررسی و هم‌رسانی کنید \ No newline at end of file From 7d9dbb09ff84ffac2368a4ef41ac54780990b648 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Tue, 3 Nov 2020 17:29:56 +0200 Subject: [PATCH 079/106] Fix import duplicates --- .../plus/activities/LocalIndexHelper.java | 2 +- .../backend/backup/DataSettingsItem.java | 2 +- .../backend/backup/FavoritesSettingsItem.java | 3 +- .../backend/backup/FileSettingsItem.java | 138 ++++++++++-------- .../backup/OsmandSettingsItemReader.java | 3 +- .../backend/backup/SettingsExporter.java | 1 - .../backend/backup/SettingsHelper.java | 7 +- .../backend/backup/SettingsImporter.java | 2 +- .../settings/backend/backup/SettingsItem.java | 2 +- .../backend/backup/SettingsItemReader.java | 3 +- .../fragments/DuplicatesSettingsAdapter.java | 28 ++-- .../ExportImportSettingsAdapter.java | 20 +-- .../fragments/ImportDuplicatesFragment.java | 51 ++++++- 13 files changed, 149 insertions(+), 113 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java b/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java index 1e53f97603..7c64e3a669 100644 --- a/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java +++ b/OsmAnd/src/net/osmand/plus/activities/LocalIndexHelper.java @@ -214,7 +214,7 @@ public class LocalIndexHelper { return result; } - public void loadVoiceData(File voiceDir, List result, boolean backup, AbstractLoadLocalIndexTask loadTask) { + private void loadVoiceData(File voiceDir, List result, boolean backup, AbstractLoadLocalIndexTask loadTask) { if (voiceDir.canRead()) { //First list TTS files, they are preferred for (File voiceF : listFilesSorted(voiceDir)) { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/DataSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/DataSettingsItem.java index 75529aa543..d040f20411 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/DataSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/DataSettingsItem.java @@ -64,7 +64,7 @@ public class DataSettingsItem extends StreamSettingsItem { SettingsItemReader getReader() { return new StreamSettingsItemReader(this) { @Override - public void readFromStream(@NonNull InputStream inputStream, File destination) throws IOException, IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, String entryName) throws IOException, IllegalArgumentException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[SettingsHelper.BUFFER]; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FavoritesSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FavoritesSettingsItem.java index a035ae0146..817ec38a49 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FavoritesSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FavoritesSettingsItem.java @@ -16,7 +16,6 @@ import net.osmand.plus.R; import org.json.JSONException; import org.json.JSONObject; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -146,7 +145,7 @@ public class FavoritesSettingsItem extends CollectionSettingsItem return new SettingsItemReader(this) { @Override - public void readFromStream(@NonNull InputStream inputStream, File destination) throws IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, String entryName) throws IllegalArgumentException { GPXFile gpxFile = GPXUtilities.loadGPXFile(inputStream); if (gpxFile.error != null) { warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType()))); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index 3b4f8568e1..62cd9df7d5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -1,5 +1,6 @@ package net.osmand.plus.settings.backend.backup; +import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -23,36 +24,34 @@ import java.util.zip.ZipOutputStream; public class FileSettingsItem extends StreamSettingsItem { public enum FileSubtype { - UNKNOWN("", null), - OTHER("other", ""), - ROUTING_CONFIG("routing_config", IndexConstants.ROUTING_PROFILES_DIR), - RENDERING_STYLE("rendering_style", IndexConstants.RENDERERS_DIR), - WIKI_MAP("wiki_map", IndexConstants.WIKI_INDEX_DIR), - SRTM_MAP("srtm_map", IndexConstants.SRTM_INDEX_DIR), - OBF_MAP("obf_map", IndexConstants.MAPS_PATH), - TILES_MAP("tiles_map", IndexConstants.TILES_INDEX_DIR), - GPX("gpx", IndexConstants.GPX_INDEX_DIR), - TTS_VOICE("tts_voice", IndexConstants.VOICE_INDEX_DIR), - VOICE("voice", IndexConstants.VOICE_INDEX_DIR), - TRAVEL("travel", IndexConstants.WIKIVOYAGE_INDEX_DIR), - MULTIMEDIA_NOTES("multimedia_notes", IndexConstants.AV_INDEX_DIR); + UNKNOWN("", null, -1), + OTHER("other", "", -1), + ROUTING_CONFIG("routing_config", IndexConstants.ROUTING_PROFILES_DIR, R.drawable.ic_action_route_distance), + RENDERING_STYLE("rendering_style", IndexConstants.RENDERERS_DIR, R.drawable.ic_action_map_style), + WIKI_MAP("wiki_map", IndexConstants.WIKI_INDEX_DIR, R.drawable.ic_plugin_wikipedia), + SRTM_MAP("srtm_map", IndexConstants.SRTM_INDEX_DIR, R.drawable.ic_plugin_srtm), + OBF_MAP("obf_map", IndexConstants.MAPS_PATH, R.drawable.ic_map), + TILES_MAP("tiles_map", IndexConstants.TILES_INDEX_DIR, R.drawable.ic_map), + GPX("gpx", IndexConstants.GPX_INDEX_DIR, R.drawable.ic_action_route_distance), + TTS_VOICE("tts_voice", IndexConstants.VOICE_INDEX_DIR, R.drawable.ic_action_volume_up), + VOICE("voice", IndexConstants.VOICE_INDEX_DIR, R.drawable.ic_action_volume_up), + TRAVEL("travel", IndexConstants.WIKIVOYAGE_INDEX_DIR, R.drawable.ic_plugin_wikipedia), + MULTIMEDIA_NOTES("multimedia_notes", IndexConstants.AV_INDEX_DIR, R.drawable.ic_action_photo_dark); - private String subtypeName; - private String subtypeFolder; + private final String subtypeName; + private final String subtypeFolder; + private final int iconId; - FileSubtype(String subtypeName, String subtypeFolder) { + FileSubtype(@NonNull String subtypeName, String subtypeFolder, @DrawableRes int iconId) { this.subtypeName = subtypeName; this.subtypeFolder = subtypeFolder; + this.iconId = iconId; } public boolean isMap() { return this == OBF_MAP || this == WIKI_MAP || this == SRTM_MAP || this == TILES_MAP; } - public boolean isDirectory() { - return this == TTS_VOICE || this == VOICE; - } - public String getSubtypeName() { return subtypeName; } @@ -61,6 +60,10 @@ public class FileSettingsItem extends StreamSettingsItem { return subtypeFolder; } + public int getIconId() { + return iconId; + } + public static FileSubtype getSubtypeByName(@NonNull String name) { for (FileSubtype subtype : FileSubtype.values()) { if (name.equals(subtype.subtypeName)) { @@ -227,15 +230,30 @@ public class FileSettingsItem extends StreamSettingsItem { return file.exists(); } - private File renameFile(File file) { + private File renameFile(File oldFile) { int number = 0; - String path = file.getAbsolutePath(); + String oldPath = oldFile.getAbsolutePath(); + String suffix; + String prefix; + if (file.isDirectory()) { + prefix = file.getAbsolutePath(); + suffix = oldPath.replace(file.getAbsolutePath(), ""); + } else if (oldPath.endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) { + prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)); + suffix = IndexConstants.BINARY_WIKI_MAP_INDEX_EXT; + } else if (oldPath.endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) { + prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)); + suffix = IndexConstants.BINARY_SRTM_MAP_INDEX_EXT; + } else { + prefix = oldPath.substring(0, oldPath.lastIndexOf(".")); + suffix = "." + Algorithms.getFileExtension(oldFile); + } while (true) { number++; - String copyName = path.replaceAll(file.getName(), file.getName().replaceFirst("[.]", "_" + number + ".")); - File copyFile = new File(copyName); - if (!copyFile.exists()) { - return copyFile; + String newName = prefix + "_" + number + suffix; + File newFile = new File(newName); + if (!newFile.exists()) { + return newFile; } } } @@ -245,8 +263,12 @@ public class FileSettingsItem extends StreamSettingsItem { SettingsItemReader getReader() { return new StreamSettingsItemReader(this) { @Override - public void readFromStream(@NonNull InputStream inputStream, File dest) throws IOException, IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, String entryName) throws IOException, IllegalArgumentException { OutputStream output; + File dest = FileSettingsItem.this.getFile(); + if (dest.isDirectory()) { + dest = new File(dest, entryName.substring(fileName.length())); + } if (dest.exists() && !shouldReplace) { dest = renameFile(dest); } @@ -271,46 +293,42 @@ public class FileSettingsItem extends StreamSettingsItem { @Nullable @Override public SettingsItemWriter getWriter() { - try { - if (!file.isDirectory()) { + if (!file.isDirectory()) { + try { setInputStream(new FileInputStream(file)); + } catch (FileNotFoundException e) { + 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); } - } catch (FileNotFoundException e) { - 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); - } - return new StreamSettingsItemWriter(this) { + return super.getWriter(); + } else { + return new StreamSettingsItemWriter(this) { - @Override - public void writeEntry(String fileName, @NonNull ZipOutputStream zos) throws IOException { - if (getSubtype().isDirectory()) { - File file = getFile(); + @Override + public void writeEntry(String fileName, @NonNull ZipOutputStream zos) throws IOException { zipDirsWithFiles(file, zos); - } else { - super.writeEntry(fileName, zos); } - } - public void zipDirsWithFiles(File f, ZipOutputStream zos) - throws IOException { - if (f == null) { - return; - } - if (f.isDirectory()) { - File[] fs = f.listFiles(); - if (fs != null) { - for (File c : fs) { - zipDirsWithFiles(c, zos); - } + public void zipDirsWithFiles(File file, ZipOutputStream zos) throws IOException { + if (file == null) { + return; + } + if (file.isDirectory()) { + File[] fs = file.listFiles(); + if (fs != null) { + for (File c : fs) { + zipDirsWithFiles(c, zos); + } + } + } else { + String zipEntryName = Algorithms.isEmpty(getSubtype().getSubtypeFolder()) + ? file.getName() + : file.getPath().substring(file.getPath().indexOf(getSubtype().getSubtypeFolder()) - 1); + setInputStream(new FileInputStream(file)); + super.writeEntry(zipEntryName, zos); } - } else { - String zipEntryName = Algorithms.isEmpty(getSubtype().getSubtypeFolder()) - ? f.getName() - : f.getPath().substring(f.getPath().indexOf(getSubtype().getSubtypeFolder()) - 1); - setInputStream(new FileInputStream(f)); - super.writeEntry(zipEntryName, zos); } - } - }; + }; + } } } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/OsmandSettingsItemReader.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/OsmandSettingsItemReader.java index df68e8a3e3..1fd27e192f 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/OsmandSettingsItemReader.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/OsmandSettingsItemReader.java @@ -10,7 +10,6 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -30,7 +29,7 @@ public abstract class OsmandSettingsItemReader ext @NonNull JSONObject json) throws JSONException; @Override - public void readFromStream(@NonNull InputStream inputStream, File destination) throws IOException, IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, String entryName) throws IOException, IllegalArgumentException { StringBuilder buf = new StringBuilder(); try { BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java index 3a697b77c0..5b27f2afb4 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java @@ -72,7 +72,6 @@ class SettingsExporter { } } - private JSONObject createItemsJson() throws JSONException { JSONObject json = new JSONObject(); json.put("version", SettingsHelper.VERSION); 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 f6cbdb4b43..469e9ebde0 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -542,9 +542,8 @@ public class SettingsHelper { if (!favoriteGroups.isEmpty()) { dataList.put(ExportSettingsType.FAVORITES, favoriteGroups); } - List localIndexInfoList = getVoiceIndexInfo(); - List files; - files = getFilesByType(localIndexInfoList, LocalIndexType.MAP_DATA, LocalIndexType.TILES_DATA, + List localIndexInfoList = getLocalIndexData(); + List files = getFilesByType(localIndexInfoList, LocalIndexType.MAP_DATA, LocalIndexType.TILES_DATA, LocalIndexType.SRTM_DATA, LocalIndexType.WIKI_DATA); if (!files.isEmpty()) { sortData(files); @@ -561,7 +560,7 @@ public class SettingsHelper { return dataList; } - private List getVoiceIndexInfo() { + private List getLocalIndexData() { return new LocalIndexHelper(app).getLocalIndexData(new AbstractLoadLocalIndexTask() { @Override public void loadFile(LocalIndexInfo... loaded) { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java index fcc1fba2f7..7f72761066 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java @@ -124,7 +124,7 @@ class SettingsImporter { try { SettingsItemReader reader = item.getReader(); if (reader != null) { - reader.readFromStream(ois, app.getAppPath(fileName)); + reader.readFromStream(ois, fileName); } } catch (IllegalArgumentException e) { item.warnings.add(app.getString(R.string.settings_item_read_error, item.getName())); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java index 815710b94c..afe776db09 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItem.java @@ -169,7 +169,7 @@ public abstract class SettingsItem { SettingsItemReader getJsonReader() { return new SettingsItemReader(this) { @Override - public void readFromStream(@NonNull InputStream inputStream, File destination) throws IOException, IllegalArgumentException { + public void readFromStream(@NonNull InputStream inputStream, String entryName) throws IOException, IllegalArgumentException { StringBuilder buf = new StringBuilder(); try { BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java index 2e38e04f08..12af0ee3c5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemReader.java @@ -2,7 +2,6 @@ package net.osmand.plus.settings.backend.backup; import androidx.annotation.NonNull; -import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -14,5 +13,5 @@ public abstract class SettingsItemReader { this.item = item; } - public abstract void readFromStream(@NonNull InputStream inputStream, File destination) throws IOException, IllegalArgumentException; + public abstract void readFromStream(@NonNull InputStream inputStream, String entryName) throws IOException, IllegalArgumentException; } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java index d90f4b7429..efda7de984 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java @@ -15,6 +15,7 @@ import net.osmand.PlatformUtil; import net.osmand.map.ITileSource; import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; import net.osmand.plus.audionotes.AudioVideoNotesPlugin; +import net.osmand.plus.helpers.FileNameTranslationHelper; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; @@ -34,6 +35,8 @@ import org.apache.commons.logging.Log; import java.io.File; import java.util.List; +import static net.osmand.plus.settings.backend.backup.FileSettingsItem.*; + public class DuplicatesSettingsAdapter extends RecyclerView.Adapter { private static final Log LOG = PlatformUtil.getLog(DuplicatesSettingsAdapter.class.getName()); @@ -75,12 +78,11 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter trackFilesList = new ArrayList<>(); List avoidRoads = new ArrayList<>(); List favoriteGroups = new ArrayList<>(); + List osmNotesPointList = new ArrayList<>(); + List osmEditsPointList = new ArrayList<>(); + List ttsVoiceFilesList = new ArrayList<>(); + List voiceFilesList = new ArrayList<>(); + List mapFilesList = new ArrayList<>(); for (Object object : duplicatesList) { if (object instanceof ApplicationMode.ApplicationModeBean) { @@ -208,19 +212,30 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment { tileSources.add((ITileSource) object); } else if (object instanceof File) { File file = (File) object; - if (file.getAbsolutePath().contains(RENDERERS_DIR)) { + FileSubtype fileSubtype = FileSubtype.getSubtypeByPath(app, file.getPath()); + if (fileSubtype == FileSubtype.RENDERING_STYLE) { renderFilesList.add(file); - } else if (file.getAbsolutePath().contains(ROUTING_PROFILES_DIR)) { + } else if (fileSubtype == FileSubtype.ROUTING_CONFIG) { routingFilesList.add(file); - } else if (file.getAbsolutePath().contains(AV_INDEX_DIR)) { + } else if (fileSubtype == FileSubtype.MULTIMEDIA_NOTES) { multimediaFilesList.add(file); - } else if (file.getAbsolutePath().contains(GPX_INDEX_DIR)) { + } else if (fileSubtype == FileSubtype.GPX) { trackFilesList.add(file); + } else if (fileSubtype.isMap()) { + mapFilesList.add(file); + } else if (fileSubtype == FileSubtype.TTS_VOICE) { + ttsVoiceFilesList.add(file); + } else if (fileSubtype == FileSubtype.VOICE) { + voiceFilesList.add(file); } } else if (object instanceof AvoidRoadInfo) { avoidRoads.add((AvoidRoadInfo) object); } else if (object instanceof FavoriteGroup) { favoriteGroups.add((FavoriteGroup) object); + } else if (object instanceof OsmNotesPoint) { + osmNotesPointList.add((OsmNotesPoint) object); + } else if (object instanceof OpenstreetmapPoint) { + osmEditsPointList.add((OpenstreetmapPoint) object); } } if (!profiles.isEmpty()) { @@ -263,6 +278,26 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment { duplicates.add(getString(R.string.shared_string_favorites)); duplicates.addAll(favoriteGroups); } + if (!osmNotesPointList.isEmpty()) { + duplicates.add(getString(R.string.osm_notes)); + duplicates.addAll(osmNotesPointList); + } + if (!osmEditsPointList.isEmpty()) { + duplicates.add(getString(R.string.osm_edits)); + duplicates.addAll(osmEditsPointList); + } + if (!mapFilesList.isEmpty()) { + duplicates.add(getString(R.string.shared_string_maps)); + duplicates.addAll(mapFilesList); + } + if (!ttsVoiceFilesList.isEmpty()) { + duplicates.add(getString(R.string.local_indexes_cat_tts)); + duplicates.addAll(ttsVoiceFilesList); + } + if (!voiceFilesList.isEmpty()) { + duplicates.add(getString(R.string.local_indexes_cat_voice)); + duplicates.addAll(voiceFilesList); + } return duplicates; } From 258410823c1842d6e1ade5b0316f4a8c09c01380 Mon Sep 17 00:00:00 2001 From: iman Date: Tue, 3 Nov 2020 20:49:34 +0000 Subject: [PATCH 080/106] Translated using Weblate (Persian) Currently translated at 36.2% (1389 of 3830 strings) --- OsmAnd/res/values-fa/phrases.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/values-fa/phrases.xml b/OsmAnd/res/values-fa/phrases.xml index dd6c374db3..28eb63e08b 100644 --- a/OsmAnd/res/values-fa/phrases.xml +++ b/OsmAnd/res/values-fa/phrases.xml @@ -226,14 +226,14 @@ صندوق بازنشستگی سازمان مهاجرت اداره مالیات - دفتر اجرایی + اداره حکومتی گمرک شهر شهر روستا دهکده سکونتگاه دورافتاده - حومه شهر + منطقه شهری محله محل @@ -346,7 +346,7 @@ اثر هنری مرکز باستان شناسی میدان جنگ - سنگ یادبود + سنگ مرز توپ تاریخی قلعه دروازه شهر @@ -1452,4 +1452,5 @@ دسترسی اتوبوس بله منطقهٔ حفاظت‌شده + بدمینتون \ No newline at end of file From 4a327a983478595c1ca1b3a2d24e76080a14ce4b Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Wed, 4 Nov 2020 15:36:44 +0100 Subject: [PATCH 081/106] Clean up gradle tasks / formatting --- .../src/main/java/net/osmand/TspAnt.java | 8 +++++--- OsmAnd/build.gradle | 20 +++---------------- .../builders/cards/ImageCard.java | 2 +- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/TspAnt.java b/OsmAnd-java/src/main/java/net/osmand/TspAnt.java index 815bddb7ef..6964a3facd 100644 --- a/OsmAnd-java/src/main/java/net/osmand/TspAnt.java +++ b/OsmAnd-java/src/main/java/net/osmand/TspAnt.java @@ -106,9 +106,11 @@ public class TspAnt { // Allocates all memory. // Adds 1 to edge lengths to ensure no zero length edges. public TspAnt readGraph(List intermediates, LatLon start, LatLon end) { - boolean keepEndPoint = end != null; - List l = new ArrayList(); - l.add(start); + boolean keepEndPoint = end != null; + List l = new ArrayList(); + if (start != null) { + l.add(start); + } l.addAll(intermediates); if (keepEndPoint) { l.add(end); diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index 3638a103ca..ea1b4ef294 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -188,38 +188,24 @@ android { dimension "version" applicationId "net.osmand" } - freeres { - dimension "version" - applicationId "net.osmand" - resConfig "en" - } - freecustom { - dimension "version" - applicationId "net.osmand.freecustom" - } full { dimension "version" applicationId "net.osmand.plus" } - fulldev { - dimension "version" - applicationId "net.osmand.plus" - resConfig "en" - // resConfigs "xxhdpi", "nodpi" - } freehuawei { dimension "version" applicationId "net.osmand.huawei" } // CoreVersion + // Build that doesn't include 3D OpenGL legacy { dimension "coreversion" } - + // Build that includes 3D OpenGL release qtcore { dimension "coreversion" } - + // Build that includes 3D OpenGL debug qtcoredebug { dimension "coreversion" } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java index c3da090ef9..26c81f03a7 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java @@ -495,7 +495,7 @@ public abstract class ImageCard extends AbstractCard { } } } catch (Exception e) { - e.printStackTrace(); + LOG.error(e); } if (listener != null) { listener.onPostProcess(result); From 11d997f55bac169ee14e370372cca7ed8d04f960 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Wed, 4 Nov 2020 15:48:32 +0100 Subject: [PATCH 082/106] Clean up gradle tasks / formatting --- OsmAnd/AndroidManifest-freecustom.xml | 25 ------------------------- OsmAnd/build.gradle | 4 ---- 2 files changed, 29 deletions(-) delete mode 100644 OsmAnd/AndroidManifest-freecustom.xml diff --git a/OsmAnd/AndroidManifest-freecustom.xml b/OsmAnd/AndroidManifest-freecustom.xml deleted file mode 100644 index 66ced1602a..0000000000 --- a/OsmAnd/AndroidManifest-freecustom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index ea1b4ef294..8272b7aab5 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -130,10 +130,6 @@ android { java.srcDirs = ["src-google"] manifest.srcFile "AndroidManifest-freedev.xml" } - freecustom { - java.srcDirs = ["src-google"] - manifest.srcFile "AndroidManifest-freecustom.xml" - } freehuawei { java.srcDirs = ["src-huawei"] manifest.srcFile "AndroidManifest-freehuawei.xml" From eb760bf9532396a5b1d6d71663eb753812338ab3 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Wed, 4 Nov 2020 15:49:48 +0100 Subject: [PATCH 083/106] Clean up gradle tasks / formatting --- OsmAnd/build.gradle | 8 -------- 1 file changed, 8 deletions(-) diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index 8272b7aab5..79a71bb781 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -119,22 +119,14 @@ android { full { java.srcDirs = ["src-google"] } - fulldev { - java.srcDirs = ["src-google"] - } free { java.srcDirs = ["src-google"] manifest.srcFile "AndroidManifest-free.xml" } - freedev { - java.srcDirs = ["src-google"] - manifest.srcFile "AndroidManifest-freedev.xml" - } freehuawei { java.srcDirs = ["src-huawei"] manifest.srcFile "AndroidManifest-freehuawei.xml" } - legacy { jniLibs.srcDirs = ["libc++"] } From 6f540bfe8a547fa3bb7a737a40bac41488ab4f06 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Wed, 4 Nov 2020 15:50:24 +0100 Subject: [PATCH 084/106] Clean up gradle tasks / formatting --- OsmAnd/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index 79a71bb781..9b89c97850 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -123,10 +123,15 @@ android { java.srcDirs = ["src-google"] manifest.srcFile "AndroidManifest-free.xml" } + freedev { + java.srcDirs = ["src-google"] + manifest.srcFile "AndroidManifest-freedev.xml" + } freehuawei { java.srcDirs = ["src-huawei"] manifest.srcFile "AndroidManifest-freehuawei.xml" } + legacy { jniLibs.srcDirs = ["libc++"] } From 312027db3c90a4f013a1fffd42cd9e63ea7add33 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Wed, 4 Nov 2020 22:29:21 +0200 Subject: [PATCH 085/106] Add export progress & cancel --- .../backend/backup/FileSettingsItem.java | 3 +- .../backend/backup/SettingsExporter.java | 23 +++++++- .../backend/backup/SettingsHelper.java | 50 +++++++++++++--- .../fragments/ExportProfileBottomSheet.java | 57 ++++++++++++++++++- .../fragments/ProfileAppearanceFragment.java | 5 ++ 5 files changed, 124 insertions(+), 14 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index 62cd9df7d5..fd28e05adc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -208,7 +208,7 @@ public class FileSettingsItem extends StreamSettingsItem { } public long getSize() { - return size; + return file != null && !file.isDirectory() ? file.length() : size; } public void setSize(long size) { @@ -273,6 +273,7 @@ public class FileSettingsItem extends StreamSettingsItem { dest = renameFile(dest); } if (dest.getParentFile() != null && !dest.getParentFile().exists()) { + //noinspection ResultOfMethodCallIgnored dest.getParentFile().mkdirs(); } output = new FileOutputStream(dest); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java index 5b27f2afb4..e97a109561 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java @@ -21,6 +21,7 @@ class SettingsExporter { private Map items; private Map additionalParams; private boolean exportItemsFiles; + private boolean exportCancel; SettingsExporter(boolean exportItemsFiles) { this.exportItemsFiles = exportItemsFiles; @@ -35,11 +36,15 @@ class SettingsExporter { items.put(item.getName(), item); } + public void setExportCancel(boolean exportCancel) { + this.exportCancel = exportCancel; + } + void addAdditionalParam(String key, String value) { additionalParams.put(key, value); } - void exportSettings(File file) throws JSONException, IOException { + void exportSettings(File file, SettingsHelper.ExportProgress exportProgress) throws JSONException, IOException { JSONObject json = createItemsJson(); OutputStream os = new BufferedOutputStream(new FileOutputStream(file), SettingsHelper.BUFFER); ZipOutputStream zos = new ZipOutputStream(os); @@ -49,7 +54,7 @@ class SettingsExporter { zos.write(json.toString(2).getBytes("UTF-8")); zos.closeEntry(); if (exportItemsFiles) { - writeItemFiles(zos); + writeItemFiles(zos, exportProgress); } zos.flush(); zos.finish(); @@ -59,7 +64,8 @@ class SettingsExporter { } } - private void writeItemFiles(ZipOutputStream zos) throws IOException { + private void writeItemFiles(ZipOutputStream zos, SettingsHelper.ExportProgress exportProgress) throws IOException { + int progress = 0; for (SettingsItem item : items.values()) { SettingsItemWriter writer = item.getWriter(); if (writer != null) { @@ -69,6 +75,17 @@ class SettingsExporter { } writer.writeEntry(fileName, zos); } + if (exportCancel) { + exportCancel = false; + return; + } + if (item instanceof FileSettingsItem) { + int size = (int) ((FileSettingsItem) item).getSize() / 1000000; + progress += size; + if (exportProgress != null) { + exportProgress.setProgress(progress); + } + } } } 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 469e9ebde0..09389bcefa 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -111,6 +111,8 @@ public class SettingsHelper { public interface SettingsExportListener { void onSettingsExportFinished(@NonNull File file, boolean succeed); + + void onSettingsExportProgressUpdate(int value); } public enum ImportType { @@ -139,6 +141,10 @@ public class SettingsHelper { return importTask == null || importTask.isImportDone(); } + public ExportAsyncTask getExportAsyncTask(File file) { + return exportAsyncTasks.get(file); + } + public boolean isFileExporting(File file) { return exportAsyncTasks.containsKey(file); } @@ -200,28 +206,41 @@ public class SettingsHelper { } } - @SuppressLint("StaticFieldLeak") - private class ExportAsyncTask extends AsyncTask { + public interface ExportProgress { + void setProgress(int value); + } - private SettingsExporter exporter; - private File file; + @SuppressLint("StaticFieldLeak") + public class ExportAsyncTask extends AsyncTask { + + private final SettingsExporter exporter; + private final File file; private SettingsExportListener listener; + private final ExportProgress exportProgress; + ExportAsyncTask(@NonNull File settingsFile, - @Nullable SettingsExportListener listener, - @NonNull List items, boolean exportItemsFiles) { + @Nullable SettingsExportListener listener, + @NonNull List items, boolean exportItemsFiles) { this.file = settingsFile; this.listener = listener; this.exporter = new SettingsExporter(exportItemsFiles); for (SettingsItem item : items) { exporter.addSettingsItem(item); } + exportProgress = new ExportProgress() { + @Override + public void setProgress(int value) { + exporter.setExportCancel(isCancelled()); + publishProgress(value); + } + }; } @Override protected Boolean doInBackground(Void... voids) { try { - exporter.exportSettings(file); + exporter.exportSettings(file, exportProgress); return true; } catch (JSONException e) { LOG.error("Failed to export items to: " + file.getName(), e); @@ -231,6 +250,14 @@ public class SettingsHelper { return false; } + @Override + protected void onProgressUpdate(Integer... values) { + super.onProgressUpdate(values); + if (listener != null) { + listener.onSettingsExportProgressUpdate(values[0]); + } + } + @Override protected void onPostExecute(Boolean success) { exportAsyncTasks.remove(file); @@ -238,6 +265,13 @@ public class SettingsHelper { listener.onSettingsExportFinished(file, success); } } + + @Override + protected void onCancelled() { + super.onCancelled(); + //noinspection ResultOfMethodCallIgnored + file.delete(); + } } @SuppressLint("StaticFieldLeak") @@ -416,6 +450,8 @@ public class SettingsHelper { public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener, @NonNull List items, boolean exportItemsFiles) { File file = new File(fileDir, fileName + OSMAND_SETTINGS_FILE_EXT); ExportAsyncTask exportAsyncTask = new ExportAsyncTask(file, listener, items, exportItemsFiles); + + exportAsyncTasks.put(file, exportAsyncTask); exportAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java index 0d621b6b50..2657e58d2a 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java @@ -2,6 +2,7 @@ package net.osmand.plus.settings.fragments; import android.app.ProgressDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.drawable.ColorDrawable; @@ -33,6 +34,7 @@ import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; import net.osmand.plus.settings.backend.ApplicationMode; 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.plus.settings.backend.backup.ProfileSettingsItem; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener; @@ -47,6 +49,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { @@ -60,8 +63,10 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { private static final String EXPORTING_PROFILE_KEY = "exporting_profile_key"; private static final String INCLUDE_ADDITIONAL_DATA_KEY = "include_additional_data_key"; private static final String INCLUDE_GLOBAL_SETTINGS_KEY = "include_global_settings_key"; + private static final String PROGRESS_MAX_KEY = "progress_max_key"; + private static final String PROGRESS_VALUE_KEY = "progress_value_key"; - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yy"); + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yy", Locale.US); private OsmandApplication app; private Map> dataList = new HashMap<>(); @@ -69,6 +74,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { private SettingsExportListener exportListener; private ProgressDialog progress; + int progressMax; + int progressValue; private long exportStartTime; @@ -87,6 +94,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY); includeGlobalSettings = savedInstanceState.getBoolean(INCLUDE_GLOBAL_SETTINGS_KEY); exportStartTime = savedInstanceState.getLong(EXPORT_START_TIME_KEY); + progressMax = savedInstanceState.getInt(PROGRESS_MAX_KEY); + progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY); } dataList = app.getSettingsHelper().getAdditionalData(globalExport); } @@ -99,6 +108,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { outState.putBoolean(INCLUDE_ADDITIONAL_DATA_KEY, includeAdditionalData); outState.putBoolean(INCLUDE_GLOBAL_SETTINGS_KEY, includeGlobalSettings); outState.putLong(EXPORT_START_TIME_KEY, exportStartTime); + outState.putInt(PROGRESS_MAX_KEY, progress.getMax()); + outState.putInt(PROGRESS_VALUE_KEY, progress.getProgress()); } @Override @@ -271,10 +282,22 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { showExportProgressDialog(); File tempDir = FileUtils.getTempDir(app); String fileName = getFileName(); - app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), prepareSettingsItemsForExport(), true); + List items = prepareSettingsItemsForExport(); + progress.setMax(getMaxProgress(items)); + app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true); } } + private int getMaxProgress(List items) { + long maxProgress = 0; + for (SettingsItem item : items) { + if (item instanceof FileSettingsItem) { + maxProgress += ((FileSettingsItem) item).getSize(); + } + } + return (int) maxProgress / 1000000; + } + private String getFileName() { if (globalExport) { if (exportStartTime == 0) { @@ -295,12 +318,33 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { progress.dismiss(); } progress = new ProgressDialog(context); + progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + progress.setCancelable(true); progress.setTitle(app.getString(R.string.shared_string_export)); progress.setMessage(app.getString(R.string.shared_string_preparing)); - progress.setCancelable(false); + progress.setButton(DialogInterface.BUTTON_NEGATIVE, app.getString(R.string.shared_string_cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + cancelExport(); + } + }); + progress.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + cancelExport(); + } + }); progress.show(); } + private void cancelExport() { + app.getSettingsHelper().getExportAsyncTask(getExportFile()).cancel(true); + //noinspection ResultOfMethodCallIgnored + getExportFile().delete(); + progress.dismiss(); + dismiss(); + } + private SettingsExportListener getSettingsExportListener() { if (exportListener == null) { exportListener = new SettingsExportListener() { @@ -315,6 +359,11 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { app.showToastMessage(R.string.export_profile_failed); } } + + @Override + public void onSettingsExportProgressUpdate(int value) { + progress.setProgress(value); + } }; } return exportListener; @@ -326,6 +375,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { boolean fileExporting = app.getSettingsHelper().isFileExporting(file); if (fileExporting) { showExportProgressDialog(); + progress.setMax(progressMax); + progress.setProgress(progressValue); app.getSettingsHelper().updateExportListener(file, getSettingsExportListener()); } else if (file.exists()) { dismissExportProgressDialog(); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java index 1bdbc38b19..bc3092d963 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java @@ -735,6 +735,11 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { app.showToastMessage(R.string.profile_backup_failed); } } + + @Override + public void onSettingsExportProgressUpdate(int value) { + + } }; } return exportListener; From beddaf82090a381b8ac244a18df90aee2399e94b Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Thu, 5 Nov 2020 01:02:16 +0200 Subject: [PATCH 086/106] Fix chart on map --- .../other/TrackDetailsMenu.java | 11 ++++-- .../plus/measurementtool/GraphsCard.java | 21 +++++++++- .../MeasurementToolFragment.java | 13 ++++++- .../plus/measurementtool/PointsCard.java | 4 +- .../graph/GraphAdapterHelper.java | 38 +++++++++++-------- .../RouteDetailsFragment.java | 11 ++---- .../osmand/plus/views/layers/RouteLayer.java | 16 +++++++- 7 files changed, 82 insertions(+), 32 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java index 1e441071a4..a45bfb27e8 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java @@ -125,8 +125,7 @@ public class TrackDetailsMenu { hidding = true; fragment.dismiss(backPressed); } else { - segment = null; - trackChartPoints = null; + reset(); } } @@ -274,8 +273,7 @@ public class TrackDetailsMenu { if (hidding) { hidding = false; visible = false; - segment = null; - trackChartPoints = null; + reset(); } } @@ -532,6 +530,11 @@ public class TrackDetailsMenu { fitTrackOnMap(chart, location, forceFit); } + public void reset() { + segment = null; + trackChartPoints = null; + } + private List getXAxisPoints(LineChart chart) { float[] entries = chart.getXAxis().mEntries; LineData lineData = chart.getLineData(); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java index 69277f19a6..3b2e979f55 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java @@ -34,6 +34,7 @@ import net.osmand.plus.measurementtool.graph.CustomGraphAdapter; import net.osmand.plus.measurementtool.graph.CustomGraphAdapter.LegendViewType; import net.osmand.plus.measurementtool.graph.BaseGraphAdapter; import net.osmand.plus.measurementtool.graph.GraphAdapterHelper; +import net.osmand.plus.measurementtool.graph.GraphAdapterHelper.RefreshMapCallback; import net.osmand.plus.routepreparationmenu.RouteDetailsFragment; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.router.RouteSegmentResult; @@ -59,6 +60,7 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen private MeasurementEditingContext editingCtx; private MeasurementToolFragment fragment; private TrackDetailsMenu trackDetailsMenu; + private RefreshMapCallback refreshMapCallback; private GPXFile gpxFile; private GPXTrackAnalysis analysis; private GpxDisplayItem gpxItem; @@ -105,7 +107,7 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen }); GraphAdapterHelper.bindGraphAdapters(commonGraphAdapter, Arrays.asList((BaseGraphAdapter) customGraphAdapter), (ViewGroup) view); - GraphAdapterHelper.bindToMap(commonGraphAdapter, mapActivity, trackDetailsMenu); + refreshMapCallback = GraphAdapterHelper.bindToMap(commonGraphAdapter, mapActivity, trackDetailsMenu); fullUpdate(); } @@ -116,7 +118,9 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen @Override public void onUpdateAdditionalInfo() { - fullUpdate(); + if (editingCtx != null) { + fullUpdate(); + } } private void fullUpdate() { @@ -126,6 +130,7 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen updateMenu(); } updateView(); + updateChartOnMap(); } private void updateMenu() { @@ -302,6 +307,13 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen } } + private void updateChartOnMap() { + if (hasVisibleGraph()) { + trackDetailsMenu.reset(); + refreshMapCallback.refreshMap(false); + } + } + private void addCommonType(int titleId, boolean canBeCalculated, boolean hasData, @@ -346,6 +358,11 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen return fragment.isProgressBarVisible(); } + public boolean hasVisibleGraph() { + return (commonGraphContainer != null && commonGraphContainer.getVisibility() == View.VISIBLE) + || (customGraphContainer != null && customGraphContainer.getVisibility() == View.VISIBLE); + } + private abstract class GraphType { private String title; private boolean canBeCalculated; diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index c92d028f02..16c8e2309c 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -553,8 +553,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } private void updateAdditionalInfoView() { - if (visibleCard instanceof OnUpdateAdditionalInfoListener) { - ((OnUpdateAdditionalInfoListener) visibleCard).onUpdateAdditionalInfo(); + updateAdditionalInfoView(pointsCard); + updateAdditionalInfoView(graphsCard); + } + + private void updateAdditionalInfoView(OnUpdateAdditionalInfoListener listener) { + if (listener != null) { + listener.onUpdateAdditionalInfo(); } } @@ -1514,6 +1519,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return type.equals(currentAdditionalInfoType); } + public boolean hasVisibleGraph() { + return graphsCard != null && graphsCard.hasVisibleGraph(); + } + private String getSuggestedFileName() { GpxData gpxData = editingCtx.getGpxData(); String displayedName = null; diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java index 9d14598856..f3b55473bc 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java @@ -24,7 +24,9 @@ public class PointsCard extends BaseCard implements OnUpdateAdditionalInfoListen @Override public void onUpdateAdditionalInfo() { - adapter.notifyDataSetChanged(); + if (adapter != null) { + adapter.notifyDataSetChanged(); + } } @Override diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/GraphAdapterHelper.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/GraphAdapterHelper.java index efacad9d50..69eb02eec7 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/graph/GraphAdapterHelper.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/GraphAdapterHelper.java @@ -5,6 +5,8 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; + import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.Entry; @@ -96,15 +98,27 @@ public class GraphAdapterHelper { } } - public static void bindToMap(final CommonGraphAdapter graphAdapter, - final MapActivity mapActivity, - final TrackDetailsMenu detailsMenu) { + public static RefreshMapCallback bindToMap(@NonNull final CommonGraphAdapter graphAdapter, + @NonNull final MapActivity mapActivity, + @NonNull final TrackDetailsMenu detailsMenu) { + final RefreshMapCallback refreshMapCallback = new RefreshMapCallback() { + @Override + public void refreshMap(boolean forceFit) { + LineChart chart = graphAdapter.getChart(); + OsmandApplication app = mapActivity.getMyApplication(); + if (!app.getRoutingHelper().isFollowingMode()) { + detailsMenu.refreshChart(chart, forceFit); + mapActivity.refreshMap(); + } + } + }; + graphAdapter.addValueSelectedListener(BIND_TO_MAP_KEY, new CommonGraphAdapter.ExternalValueSelectedListener() { @Override public void onValueSelected(Entry e, Highlight h) { - refreshChart(mapActivity, graphAdapter.getChart(), detailsMenu, false); + refreshMapCallback.refreshMap(false); } @Override @@ -125,21 +139,15 @@ public class GraphAdapterHelper { lastPerformedGesture == ChartTouchListener.ChartGesture.PINCH_ZOOM || lastPerformedGesture == ChartTouchListener.ChartGesture.DOUBLE_TAP || lastPerformedGesture == ChartTouchListener.ChartGesture.ROTATE) { - refreshChart(mapActivity, graphAdapter.getChart(), detailsMenu, true); + refreshMapCallback.refreshMap(true); } } }); + + return refreshMapCallback; } - public static void refreshChart(MapActivity mapActivity, - LineChart chart, - TrackDetailsMenu menu, - boolean forceFit) { - if (mapActivity == null || chart == null || menu == null) return; - OsmandApplication app = mapActivity.getMyApplication(); - if (!app.getRoutingHelper().isFollowingMode()) { - menu.refreshChart(chart, forceFit); - mapActivity.refreshMap(); - } + public interface RefreshMapCallback { + void refreshMap(boolean forceFit); } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java index c6dcac20a6..780186b068 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java @@ -60,6 +60,7 @@ import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.measurementtool.graph.BaseGraphAdapter; import net.osmand.plus.measurementtool.graph.CommonGraphAdapter; import net.osmand.plus.measurementtool.graph.GraphAdapterHelper; +import net.osmand.plus.measurementtool.graph.GraphAdapterHelper.RefreshMapCallback; import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; @@ -113,6 +114,7 @@ public class RouteDetailsFragment extends ContextMenuFragment private RouteStatisticCard statisticCard; private List routeInfoCards = new ArrayList<>(); private RouteDetailsMenu routeDetailsMenu; + private RefreshMapCallback refreshMapCallback; public interface RouteDetailsFragmentListener { void onNavigationRequested(); @@ -336,7 +338,7 @@ public class RouteDetailsFragment extends ContextMenuFragment CommonGraphAdapter mainGraphAdapter = statisticCard.getGraphAdapter(); if (mainGraphAdapter != null) { GraphAdapterHelper.bindGraphAdapters(mainGraphAdapter, getRouteInfoCardsGraphAdapters(), getMainView()); - GraphAdapterHelper.bindToMap(mainGraphAdapter, mapActivity, routeDetailsMenu); + refreshMapCallback = GraphAdapterHelper.bindToMap(mainGraphAdapter, mapActivity, routeDetailsMenu); } } @@ -369,12 +371,7 @@ public class RouteDetailsFragment extends ContextMenuFragment protected void calculateLayout(View view, boolean initLayout) { super.calculateLayout(view, initLayout); if (!initLayout && getCurrentMenuState() != MenuState.FULL_SCREEN) { - MapActivity mapActivity = getMapActivity(); - CommonGraphAdapter mainGraphAdapter = statisticCard.getGraphAdapter(); - if (mainGraphAdapter != null) { - LineChart chart = mainGraphAdapter.getChart(); - GraphAdapterHelper.refreshChart(mapActivity, chart, routeDetailsMenu, false); - } + refreshMapCallback.refreshMap(false); } } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java index 8491f24a67..f966b7d897 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java @@ -26,7 +26,9 @@ import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; import net.osmand.data.TransportStop; import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; +import net.osmand.plus.measurementtool.MeasurementToolFragment; import net.osmand.plus.profiles.LocationIcon; import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RouteDirectionInfo; @@ -158,7 +160,8 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont @Override public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { if ((helper.isPublicTransportMode() && transportHelper.getRoutes() != null) || - (helper.getFinalLocation() != null && helper.getRoute().isCalculated())) { + (helper.getFinalLocation() != null && helper.getRoute().isCalculated()) || + isPlanRouteGraphsAvailable()) { updateAttrs(settings, tileBox); @@ -202,6 +205,17 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont } + private boolean isPlanRouteGraphsAvailable() { + if (view.getContext() instanceof MapActivity) { + MapActivity mapActivity = (MapActivity) view.getContext(); + MeasurementToolFragment fragment = mapActivity.getMeasurementToolFragment(); + if (fragment != null) { + return fragment.hasVisibleGraph(); + } + } + return false; + } + private void updateAttrs(DrawSettings settings, RotatedTileBox tileBox) { boolean updatePaints = attrs.updatePaints(view.getApplication(), settings, tileBox); attrs.isPaint3 = false; From bd45e5aba8464835fdacc69c7b10d1b8e3e62a79 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Thu, 5 Nov 2020 01:37:05 +0200 Subject: [PATCH 087/106] Show only two graphs on chart, refactor getDataSets --- .../net/osmand/plus/helpers/GpxUiHelper.java | 66 +++++++------------ .../plus/measurementtool/GraphsCard.java | 22 ++++--- .../plus/myplaces/TrackSegmentFragment.java | 10 +-- 3 files changed, 43 insertions(+), 55 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index dd2a35a9a4..2b91e0a6b7 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -2056,52 +2056,34 @@ public class GpxUiHelper { public static List getDataSets(LineChart chart, OsmandApplication app, GPXTrackAnalysis analysis, - boolean calcWithoutGaps, - LineGraphType ... types) { - if (app == null || chart == null || analysis == null || types == null) { + @NonNull LineGraphType firstType, + @Nullable LineGraphType secondType, + boolean calcWithoutGaps) { + if (app == null || chart == null || analysis == null) { return new ArrayList<>(); } - if (types.length > 1) { - return getDataSetsImpl(chart, app, analysis, calcWithoutGaps, types[0], types[1]); - } else { - return getDataSetsImpl(chart, app, analysis, calcWithoutGaps, types[0]); - } - } - - private static List getDataSetsImpl(@NonNull LineChart chart, - @NonNull OsmandApplication app, - @NonNull GPXTrackAnalysis analysis, - boolean calcWithoutGaps, - @NonNull LineGraphType type) { List result = new ArrayList<>(); - ILineDataSet dataSet = getDataSet(chart, app, analysis, calcWithoutGaps, false, type); - if (dataSet != null) { - result.add(dataSet); - } - return result; - } - - private static List getDataSetsImpl(@NonNull LineChart chart, - @NonNull OsmandApplication app, - @NonNull GPXTrackAnalysis analysis, - boolean calcWithoutGaps, - @NonNull LineGraphType type1, - @NonNull LineGraphType type2) { - List result = new ArrayList<>(); - OrderedLineDataSet dataSet1 = getDataSet(chart, app, analysis, calcWithoutGaps, false, type1); - OrderedLineDataSet dataSet2 = getDataSet(chart, app, analysis, calcWithoutGaps, true, type2); - if (dataSet1 == null && dataSet2 == null) { - return new ArrayList<>(); - } else if (dataSet1 == null) { - result.add(dataSet2); - } else if (dataSet2 == null) { - result.add(dataSet1); - } else if (dataSet1.getPriority() < dataSet2.getPriority()) { - result.add(dataSet2); - result.add(dataSet1); + if (secondType == null) { + ILineDataSet dataSet = getDataSet(chart, app, analysis, calcWithoutGaps, false, firstType); + if (dataSet != null) { + result.add(dataSet); + } } else { - result.add(dataSet1); - result.add(dataSet2); + OrderedLineDataSet dataSet1 = getDataSet(chart, app, analysis, calcWithoutGaps, false, firstType); + OrderedLineDataSet dataSet2 = getDataSet(chart, app, analysis, calcWithoutGaps, true, secondType); + if (dataSet1 == null && dataSet2 == null) { + return new ArrayList<>(); + } else if (dataSet1 == null) { + result.add(dataSet2); + } else if (dataSet2 == null) { + result.add(dataSet1); + } else if (dataSet1.getPriority() < dataSet2.getPriority()) { + result.add(dataSet2); + result.add(dataSet1); + } else { + result.add(dataSet1); + result.add(dataSet2); + } } return result; } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java index 3b2e979f55..9a64d77433 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java @@ -8,6 +8,7 @@ import android.widget.TextView; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -293,9 +294,9 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen boolean hasElevationData = analysis.hasElevationData; boolean hasSpeedData = analysis.isSpeedSpecified(); addCommonType(R.string.shared_string_overview, true, hasElevationData, ALTITUDE, SLOPE); - addCommonType(R.string.altitude, true, hasElevationData, ALTITUDE); - addCommonType(R.string.shared_string_slope, true, hasElevationData, SLOPE); - addCommonType(R.string.map_widget_speed, false, hasSpeedData, SPEED); + addCommonType(R.string.altitude, true, hasElevationData, ALTITUDE, null); + addCommonType(R.string.shared_string_slope, true, hasElevationData, SLOPE, null); + addCommonType(R.string.map_widget_speed, false, hasSpeedData, SPEED, null); // update custom graph data List routeStatistics = calculateRouteStatistics(); @@ -317,10 +318,11 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen private void addCommonType(int titleId, boolean canBeCalculated, boolean hasData, - LineGraphType ... lineGraphTypes) { + LineGraphType firstType, + LineGraphType secondType) { OsmandApplication app = getMyApplication(); String title = app.getString(titleId); - graphTypes.add(new CommonGraphType(title, canBeCalculated, hasData, lineGraphTypes)); + graphTypes.add(new CommonGraphType(title, canBeCalculated, hasData, firstType, secondType)); } private void setupVisibleType() { @@ -400,12 +402,14 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen private class CommonGraphType extends GraphType { private boolean hasData; - private LineGraphType[] lineGraphTypes; + private LineGraphType firstType; + private LineGraphType secondType; - public CommonGraphType(String title, boolean canBeCalculated, boolean hasData, LineGraphType ... lineGraphTypes) { + public CommonGraphType(String title, boolean canBeCalculated, boolean hasData, @NonNull LineGraphType firstType, @Nullable LineGraphType secondType) { super(title, canBeCalculated); this.hasData = hasData; - this.lineGraphTypes = lineGraphTypes; + this.firstType = firstType; + this.secondType = secondType; } @Override @@ -417,7 +421,7 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen public LineData getChartData() { GpxUiHelper.setupGPXChart(commonGraphAdapter.getChart(), 4, 24f, 16f, !nightMode, true); List dataSets = GpxUiHelper.getDataSets(commonGraphAdapter.getChart(), - app, analysis, false, lineGraphTypes); + app, analysis, firstType, secondType, false); return !Algorithms.isEmpty(dataSets) ? new LineData(dataSets) : null; } } diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java index 7a7178c578..e53b51cf39 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java @@ -62,6 +62,7 @@ import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.OsmAndListFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.helpers.GpxUiHelper.LineGraphType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; @@ -430,13 +431,14 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit private List getDataSets(LineChart chart, GPXTabItemType tabType, - GpxUiHelper.LineGraphType... types) { + LineGraphType firstType, + LineGraphType secondType) { List dataSets = dataSetsMap.get(tabType); if (dataSets == null && chart != null) { GPXTrackAnalysis analysis = gpxItem.analysis; GpxDataItem gpxDataItem = getGpxDataItem(); boolean calcWithoutGaps = gpxItem.isGeneralTrack() && gpxDataItem != null && !gpxDataItem.isJoinSegments(); - dataSets = GpxUiHelper.getDataSets(chart, app, analysis, calcWithoutGaps, types); + dataSets = GpxUiHelper.getDataSets(chart, app, analysis, firstType, secondType, calcWithoutGaps); dataSetsMap.put(tabType, dataSets); } return dataSets; @@ -878,7 +880,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit if (analysis != null && analysis.isSpeedSpecified()) { if (analysis.hasSpeedData) { GpxUiHelper.setupGPXChart(app, chart, 4); - chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_SPEED, SPEED))); + chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_SPEED, SPEED, null))); updateChart(chart); chart.setVisibility(View.VISIBLE); } else { @@ -1144,7 +1146,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit LatLon location = null; WptPt wpt = null; gpxItem.chartTypes = null; - List ds = getDataSets(null, tabType); + List ds = getDataSets(null, tabType, null, null); if (ds != null && ds.size() > 0) { gpxItem.chartTypes = new GPXDataSetType[ds.size()]; for (int i = 0; i < ds.size(); i++) { From b1ddd40ec834a3bd188a0b5934c2a8b1d98ce977 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Thu, 5 Nov 2020 02:04:25 +0200 Subject: [PATCH 088/106] small fixes --- .../src/net/osmand/plus/measurementtool/GraphsCard.java | 4 ++-- .../plus/measurementtool/graph/CustomGraphAdapter.java | 4 ++-- .../plus/measurementtool/graph/GraphAdapterHelper.java | 8 +++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java index 9a64d77433..a0f74d34db 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java @@ -42,7 +42,7 @@ import net.osmand.router.RouteSegmentResult; import net.osmand.util.Algorithms; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import static net.osmand.GPXUtilities.GPXFile; @@ -107,7 +107,7 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen } }); - GraphAdapterHelper.bindGraphAdapters(commonGraphAdapter, Arrays.asList((BaseGraphAdapter) customGraphAdapter), (ViewGroup) view); + GraphAdapterHelper.bindGraphAdapters(commonGraphAdapter, Collections.singletonList((BaseGraphAdapter) customGraphAdapter), (ViewGroup) view); refreshMapCallback = GraphAdapterHelper.bindToMap(commonGraphAdapter, mapActivity, trackDetailsMenu); fullUpdate(); } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java index 72ccff4604..1bc763b165 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/graph/CustomGraphAdapter.java @@ -29,7 +29,7 @@ import net.osmand.router.RouteStatisticsHelper.RouteSegmentAttribute; import net.osmand.util.Algorithms; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import static net.osmand.plus.track.ColorsCard.MINIMUM_CONTRAST_RATIO; @@ -122,7 +122,7 @@ public class CustomGraphAdapter extends BaseGraphAdapter Date: Thu, 5 Nov 2020 13:29:59 +0200 Subject: [PATCH 089/106] Fix review --- .../backend/backup/FileSettingsItem.java | 20 +++++++++---------- .../backend/backup/SettingsExporter.java | 18 ++++++++++------- .../backend/backup/SettingsHelper.java | 16 +++++++-------- .../fragments/ExportProfileBottomSheet.java | 8 +++----- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index fd28e05adc..dc001eb9f5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -24,14 +24,15 @@ import java.util.zip.ZipOutputStream; public class FileSettingsItem extends StreamSettingsItem { public enum FileSubtype { - UNKNOWN("", null, -1), - OTHER("other", "", -1), + UNKNOWN("", null, R.drawable.ic_type_file), + OTHER("other", "", R.drawable.ic_type_file), ROUTING_CONFIG("routing_config", IndexConstants.ROUTING_PROFILES_DIR, R.drawable.ic_action_route_distance), RENDERING_STYLE("rendering_style", IndexConstants.RENDERERS_DIR, R.drawable.ic_action_map_style), WIKI_MAP("wiki_map", IndexConstants.WIKI_INDEX_DIR, R.drawable.ic_plugin_wikipedia), SRTM_MAP("srtm_map", IndexConstants.SRTM_INDEX_DIR, R.drawable.ic_plugin_srtm), OBF_MAP("obf_map", IndexConstants.MAPS_PATH, R.drawable.ic_map), TILES_MAP("tiles_map", IndexConstants.TILES_INDEX_DIR, R.drawable.ic_map), + ROAD_MAP("road_map", IndexConstants.ROADS_INDEX_DIR, R.drawable.ic_map), GPX("gpx", IndexConstants.GPX_INDEX_DIR, R.drawable.ic_action_route_distance), TTS_VOICE("tts_voice", IndexConstants.VOICE_INDEX_DIR, R.drawable.ic_action_volume_up), VOICE("voice", IndexConstants.VOICE_INDEX_DIR, R.drawable.ic_action_volume_up), @@ -49,7 +50,7 @@ public class FileSettingsItem extends StreamSettingsItem { } public boolean isMap() { - return this == OBF_MAP || this == WIKI_MAP || this == SRTM_MAP || this == TILES_MAP; + return this == OBF_MAP || this == WIKI_MAP || this == SRTM_MAP || this == TILES_MAP || this == ROAD_MAP; } public String getSubtypeName() { @@ -60,6 +61,7 @@ public class FileSettingsItem extends StreamSettingsItem { return subtypeFolder; } + @DrawableRes public int getIconId() { return iconId; } @@ -208,7 +210,7 @@ public class FileSettingsItem extends StreamSettingsItem { } public long getSize() { - return file != null && !file.isDirectory() ? file.length() : size; + return size == 0 ? file != null && !file.isDirectory() ? file.length() : size : size; } public void setSize(long size) { @@ -231,23 +233,21 @@ public class FileSettingsItem extends StreamSettingsItem { } private File renameFile(File oldFile) { - int number = 0; String oldPath = oldFile.getAbsolutePath(); - String suffix; String prefix; if (file.isDirectory()) { prefix = file.getAbsolutePath(); - suffix = oldPath.replace(file.getAbsolutePath(), ""); } else if (oldPath.endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) { prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)); - suffix = IndexConstants.BINARY_WIKI_MAP_INDEX_EXT; } else if (oldPath.endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) { prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)); - suffix = IndexConstants.BINARY_SRTM_MAP_INDEX_EXT; + } else if (oldPath.endsWith(IndexConstants.BINARY_ROAD_MAP_INDEX_EXT)) { + prefix = oldPath.substring(0, oldPath.lastIndexOf(IndexConstants.BINARY_ROAD_MAP_INDEX_EXT)); } else { prefix = oldPath.substring(0, oldPath.lastIndexOf(".")); - suffix = "." + Algorithms.getFileExtension(oldFile); } + String suffix = oldPath.replace(prefix, ""); + int number = 0; while (true) { number++; String newName = prefix + "_" + number + suffix; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java index e97a109561..40917bd7c5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java @@ -16,15 +16,19 @@ import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import static net.osmand.plus.settings.backend.backup.SettingsHelper.*; + class SettingsExporter { private Map items; private Map additionalParams; private boolean exportItemsFiles; private boolean exportCancel; + private final ExportProgress exportProgress; - SettingsExporter(boolean exportItemsFiles) { + SettingsExporter(boolean exportItemsFiles, ExportProgress exportProgress) { this.exportItemsFiles = exportItemsFiles; + this.exportProgress = exportProgress; items = new LinkedHashMap<>(); additionalParams = new LinkedHashMap<>(); } @@ -44,9 +48,9 @@ class SettingsExporter { additionalParams.put(key, value); } - void exportSettings(File file, SettingsHelper.ExportProgress exportProgress) throws JSONException, IOException { + void exportSettings(File file) throws JSONException, IOException { JSONObject json = createItemsJson(); - OutputStream os = new BufferedOutputStream(new FileOutputStream(file), SettingsHelper.BUFFER); + OutputStream os = new BufferedOutputStream(new FileOutputStream(file), BUFFER); ZipOutputStream zos = new ZipOutputStream(os); try { ZipEntry entry = new ZipEntry("items.json"); @@ -54,7 +58,7 @@ class SettingsExporter { zos.write(json.toString(2).getBytes("UTF-8")); zos.closeEntry(); if (exportItemsFiles) { - writeItemFiles(zos, exportProgress); + writeItemFiles(zos); } zos.flush(); zos.finish(); @@ -64,7 +68,7 @@ class SettingsExporter { } } - private void writeItemFiles(ZipOutputStream zos, SettingsHelper.ExportProgress exportProgress) throws IOException { + private void writeItemFiles(ZipOutputStream zos) throws IOException { int progress = 0; for (SettingsItem item : items.values()) { SettingsItemWriter writer = item.getWriter(); @@ -80,7 +84,7 @@ class SettingsExporter { return; } if (item instanceof FileSettingsItem) { - int size = (int) ((FileSettingsItem) item).getSize() / 1000000; + int size = (int) ((FileSettingsItem) item).getSize() / (1 << 20); progress += size; if (exportProgress != null) { exportProgress.setProgress(progress); @@ -91,7 +95,7 @@ class SettingsExporter { private JSONObject createItemsJson() throws JSONException { JSONObject json = new JSONObject(); - json.put("version", SettingsHelper.VERSION); + json.put("version", VERSION); for (Map.Entry param : additionalParams.entrySet()) { json.put(param.getKey(), param.getValue()); } 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 09389bcefa..a9b66189ad 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -216,7 +216,6 @@ public class SettingsHelper { private final SettingsExporter exporter; private final File file; private SettingsExportListener listener; - private final ExportProgress exportProgress; ExportAsyncTask(@NonNull File settingsFile, @@ -224,23 +223,23 @@ public class SettingsHelper { @NonNull List items, boolean exportItemsFiles) { this.file = settingsFile; this.listener = listener; - this.exporter = new SettingsExporter(exportItemsFiles); - for (SettingsItem item : items) { - exporter.addSettingsItem(item); - } - exportProgress = new ExportProgress() { + ExportProgress exportProgress = new ExportProgress() { @Override public void setProgress(int value) { exporter.setExportCancel(isCancelled()); publishProgress(value); } }; + this.exporter = new SettingsExporter(exportItemsFiles, exportProgress); + for (SettingsItem item : items) { + exporter.addSettingsItem(item); + } } @Override protected Boolean doInBackground(Void... voids) { try { - exporter.exportSettings(file, exportProgress); + exporter.exportSettings(file); return true; } catch (JSONException e) { LOG.error("Failed to export items to: " + file.getName(), e); @@ -252,7 +251,6 @@ public class SettingsHelper { @Override protected void onProgressUpdate(Integer... values) { - super.onProgressUpdate(values); if (listener != null) { listener.onSettingsExportProgressUpdate(values[0]); } @@ -843,7 +841,7 @@ public class SettingsHelper { return settingsToOperate; } - public void sortData(List files) { + private void sortData(List files) { final Collator collator = OsmAndCollator.primaryCollator(); Collections.sort(files, new Comparator() { @Override diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java index 2657e58d2a..ba1d630bef 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java @@ -74,8 +74,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { private SettingsExportListener exportListener; private ProgressDialog progress; - int progressMax; - int progressValue; + private int progressMax; + private int progressValue; private long exportStartTime; @@ -295,7 +295,7 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { maxProgress += ((FileSettingsItem) item).getSize(); } } - return (int) maxProgress / 1000000; + return (int) maxProgress / (1 << 20); } private String getFileName() { @@ -339,8 +339,6 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { private void cancelExport() { app.getSettingsHelper().getExportAsyncTask(getExportFile()).cancel(true); - //noinspection ResultOfMethodCallIgnored - getExportFile().delete(); progress.dismiss(); dismiss(); } From 46ffc11ce3138417be2310afb8c55401850f007c Mon Sep 17 00:00:00 2001 From: Dmitry Date: Thu, 5 Nov 2020 16:43:39 +0200 Subject: [PATCH 090/106] Added icons for location permission dialog --- .../drawable/ic_action_device_location.xml | 30 +++++++++++++++++++ .../ic_action_device_location_colored.xml | 30 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 OsmAnd/res/drawable/ic_action_device_location.xml create mode 100644 OsmAnd/res/drawable/ic_action_device_location_colored.xml diff --git a/OsmAnd/res/drawable/ic_action_device_location.xml b/OsmAnd/res/drawable/ic_action_device_location.xml new file mode 100644 index 0000000000..c804224052 --- /dev/null +++ b/OsmAnd/res/drawable/ic_action_device_location.xml @@ -0,0 +1,30 @@ + + + + + + + diff --git a/OsmAnd/res/drawable/ic_action_device_location_colored.xml b/OsmAnd/res/drawable/ic_action_device_location_colored.xml new file mode 100644 index 0000000000..2bceb2d67e --- /dev/null +++ b/OsmAnd/res/drawable/ic_action_device_location_colored.xml @@ -0,0 +1,30 @@ + + + + + + + + + From f5cf80818e8b68c64fcb95da46ecc9bf6c7b4942 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Thu, 5 Nov 2020 18:18:58 +0200 Subject: [PATCH 091/106] Fix hillshade names --- OsmAnd/src/net/osmand/plus/download/IndexItem.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/download/IndexItem.java b/OsmAnd/src/net/osmand/plus/download/IndexItem.java index 7173dfca66..650ab0679b 100644 --- a/OsmAnd/src/net/osmand/plus/download/IndexItem.java +++ b/OsmAnd/src/net/osmand/plus/download/IndexItem.java @@ -143,9 +143,9 @@ public class IndexItem implements Comparable { public String getTranslatedBasename() { if (type == DownloadActivityType.HILLSHADE_FILE) { - return (FileNameTranslationHelper.HILL_SHADE + getBasename()).replace("_", " "); + return (FileNameTranslationHelper.HILL_SHADE + "_" + getBasename()).replace("_", " "); } else if (type == DownloadActivityType.SLOPE_FILE) { - return (FileNameTranslationHelper.SLOPE + getBasename()).replace('_', ' '); + return (FileNameTranslationHelper.SLOPE + "_" + getBasename()).replace('_', ' '); } else { return getBasename(); } From 1b3247780ad2cd0119f09c89537a8f8138806481 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Thu, 5 Nov 2020 18:38:52 +0200 Subject: [PATCH 092/106] Small clean up --- .../backend/backup/FileSettingsItem.java | 39 ++++++++------ .../backend/backup/SettingsExporter.java | 22 ++++---- .../backend/backup/SettingsHelper.java | 53 ++++++++++--------- .../fragments/ExportProfileBottomSheet.java | 2 +- 4 files changed, 62 insertions(+), 54 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index dc001eb9f5..563a04fc75 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -210,7 +210,12 @@ public class FileSettingsItem extends StreamSettingsItem { } public long getSize() { - return size == 0 ? file != null && !file.isDirectory() ? file.length() : size : size; + if (size != 0) { + return size; + } else if (file != null && !file.isDirectory()) { + return file.length(); + } + return 0; } public void setSize(long size) { @@ -307,26 +312,26 @@ public class FileSettingsItem extends StreamSettingsItem { @Override public void writeEntry(String fileName, @NonNull ZipOutputStream zos) throws IOException { - zipDirsWithFiles(file, zos); + writeDirWithFiles(file, zos); } - public void zipDirsWithFiles(File file, ZipOutputStream zos) throws IOException { - if (file == null) { - return; - } - if (file.isDirectory()) { - File[] fs = file.listFiles(); - if (fs != null) { - for (File c : fs) { - zipDirsWithFiles(c, zos); + public void writeDirWithFiles(File file, ZipOutputStream zos) throws IOException { + if (file != null) { + if (file.isDirectory()) { + File[] files = file.listFiles(); + if (files != null) { + for (File subfolderFile : files) { + writeDirWithFiles(subfolderFile, zos); + } } + } else { + String subtypeFolder = getSubtype().getSubtypeFolder(); + String zipEntryName = Algorithms.isEmpty(subtypeFolder) + ? file.getName() + : file.getPath().substring(file.getPath().indexOf(subtypeFolder) - 1); + setInputStream(new FileInputStream(file)); + super.writeEntry(zipEntryName, zos); } - } else { - String zipEntryName = Algorithms.isEmpty(getSubtype().getSubtypeFolder()) - ? file.getName() - : file.getPath().substring(file.getPath().indexOf(getSubtype().getSubtypeFolder()) - 1); - setInputStream(new FileInputStream(file)); - super.writeEntry(zipEntryName, zos); } } }; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java index 40917bd7c5..38c637e0c7 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java @@ -22,13 +22,14 @@ class SettingsExporter { private Map items; private Map additionalParams; - private boolean exportItemsFiles; - private boolean exportCancel; - private final ExportProgress exportProgress; + private ExportProgressListener progressListener; - SettingsExporter(boolean exportItemsFiles, ExportProgress exportProgress) { + private boolean cancelled; + private boolean exportItemsFiles; + + SettingsExporter(ExportProgressListener progressListener, boolean exportItemsFiles) { + this.progressListener = progressListener; this.exportItemsFiles = exportItemsFiles; - this.exportProgress = exportProgress; items = new LinkedHashMap<>(); additionalParams = new LinkedHashMap<>(); } @@ -40,8 +41,8 @@ class SettingsExporter { items.put(item.getName(), item); } - public void setExportCancel(boolean exportCancel) { - this.exportCancel = exportCancel; + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; } void addAdditionalParam(String key, String value) { @@ -79,15 +80,14 @@ class SettingsExporter { } writer.writeEntry(fileName, zos); } - if (exportCancel) { - exportCancel = false; + if (cancelled) { return; } if (item instanceof FileSettingsItem) { int size = (int) ((FileSettingsItem) item).getSize() / (1 << 20); progress += size; - if (exportProgress != null) { - exportProgress.setProgress(progress); + if (progressListener != null) { + progressListener.updateProgress(progress); } } } 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 a9b66189ad..9c47589674 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -37,6 +37,7 @@ import net.osmand.plus.quickaction.QuickActionRegistry; 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.util.Algorithms; import org.apache.commons.logging.Log; import org.json.JSONException; @@ -53,8 +54,8 @@ import java.util.Map; import java.util.Set; import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT; -import static net.osmand.plus.settings.backend.backup.FileSettingsItem.*; import static net.osmand.plus.activities.LocalIndexHelper.LocalIndexType; +import static net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype; /* Usage: @@ -141,8 +142,12 @@ public class SettingsHelper { return importTask == null || importTask.isImportDone(); } - public ExportAsyncTask getExportAsyncTask(File file) { - return exportAsyncTasks.get(file); + public boolean cancelExportForFile(File file) { + ExportAsyncTask exportTask = exportAsyncTasks.get(file); + if (exportTask != null && (exportTask.getStatus() == AsyncTask.Status.RUNNING)) { + return exportTask.cancel(true); + } + return false; } public boolean isFileExporting(File file) { @@ -206,31 +211,23 @@ public class SettingsHelper { } } - public interface ExportProgress { - void setProgress(int value); + public interface ExportProgressListener { + void updateProgress(int value); } @SuppressLint("StaticFieldLeak") public class ExportAsyncTask extends AsyncTask { - private final SettingsExporter exporter; - private final File file; + private File file; + private SettingsExporter exporter; private SettingsExportListener listener; - ExportAsyncTask(@NonNull File settingsFile, - @Nullable SettingsExportListener listener, - @NonNull List items, boolean exportItemsFiles) { + @Nullable SettingsExportListener listener, + @NonNull List items, boolean exportItemsFiles) { this.file = settingsFile; this.listener = listener; - ExportProgress exportProgress = new ExportProgress() { - @Override - public void setProgress(int value) { - exporter.setExportCancel(isCancelled()); - publishProgress(value); - } - }; - this.exporter = new SettingsExporter(exportItemsFiles, exportProgress); + this.exporter = new SettingsExporter(getProgressListener(), exportItemsFiles); for (SettingsItem item : items) { exporter.addSettingsItem(item); } @@ -266,9 +263,17 @@ public class SettingsHelper { @Override protected void onCancelled() { - super.onCancelled(); - //noinspection ResultOfMethodCallIgnored - file.delete(); + Algorithms.removeAllFiles(file); + } + + private ExportProgressListener getProgressListener() { + return new ExportProgressListener() { + @Override + public void updateProgress(int value) { + exporter.setCancelled(isCancelled()); + publishProgress(value); + } + }; } } @@ -448,8 +453,6 @@ public class SettingsHelper { public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener, @NonNull List items, boolean exportItemsFiles) { File file = new File(fileDir, fileName + OSMAND_SETTINGS_FILE_EXT); ExportAsyncTask exportAsyncTask = new ExportAsyncTask(file, listener, items, exportItemsFiles); - - exportAsyncTasks.put(file, exportAsyncTask); exportAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -580,7 +583,7 @@ public class SettingsHelper { List files = getFilesByType(localIndexInfoList, LocalIndexType.MAP_DATA, LocalIndexType.TILES_DATA, LocalIndexType.SRTM_DATA, LocalIndexType.WIKI_DATA); if (!files.isEmpty()) { - sortData(files); + sortLocalFiles(files); dataList.put(ExportSettingsType.OFFLINE_MAPS, files); } files = getFilesByType(localIndexInfoList, LocalIndexType.TTS_VOICE_DATA); @@ -841,7 +844,7 @@ public class SettingsHelper { return settingsToOperate; } - private void sortData(List files) { + private void sortLocalFiles(List files) { final Collator collator = OsmAndCollator.primaryCollator(); Collections.sort(files, new Comparator() { @Override diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java index ba1d630bef..8d5b484dfb 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java @@ -338,7 +338,7 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { } private void cancelExport() { - app.getSettingsHelper().getExportAsyncTask(getExportFile()).cancel(true); + app.getSettingsHelper().cancelExportForFile(getExportFile()); progress.dismiss(); dismiss(); } From 81b4dc6e8ecfaeb1f51e95b19a91d43435606d4c Mon Sep 17 00:00:00 2001 From: Michal L Date: Thu, 5 Nov 2020 22:06:00 +0000 Subject: [PATCH 093/106] Translated using Weblate (Polish) Currently translated at 99.3% (3501 of 3524 strings) --- OsmAnd/res/values-pl/strings.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/values-pl/strings.xml b/OsmAnd/res/values-pl/strings.xml index 13ddd2c001..a523ac90ad 100644 --- a/OsmAnd/res/values-pl/strings.xml +++ b/OsmAnd/res/values-pl/strings.xml @@ -3675,7 +3675,7 @@ Zakupy w OsmAnd Opłata zostanie pobrana z twojego konta Google Play przy potwierdzeniu zakupu. \n -\nSubskrypcja automatycznie odnawia się, chyba że anulujesz ją przed dniem odnowienia. Twoje konto zostanie obciążone za okres odnowienia (miesiąc/trzy miesiące/rok) dopiero w dniu odnowienia. +\nSubskrypcja automatycznie odnawia się, chyba że anulujesz ją przed dniem odnowienia. Twoje konto zostanie obciążone za okres odnowienia (miesiąc/trzy miesiące/rok) dopiero w dniu odnowienia. \n \nMożesz zarządzać subskrypcjami i anulować je w ustawieniach Google Play. • Nowe mapy stoków offline @@ -3802,7 +3802,7 @@ Przyciski głośności jako powiększenie Wózek inwalidzki Gokart - Zamknięta notatka OSM + Zamknięta uwaga OSM Aby kontynuować, musisz ustawić dni robocze Droga pomiędzy punktami Zaplanuj trasę @@ -3844,7 +3844,7 @@ Czy na pewno chcesz odrzucić wszystkie zmiany w zaplanowanej trasie, zamykając ją\? W przypadku odwrotnego kierunku Przejdź z mojej lokalizacji na trasę - Wózek naprzód + Wózek inwalidzki naprzód Ślady Podążanie za śladem Wybierz plik śladu do śledzenia lub zaimportuj go z urządzenia. @@ -3935,4 +3935,6 @@ Wylogowanie powiodło się Plik jest już zaimportowany do OsmAnd %1$s — %2$s + MGRS + MGRS \ No newline at end of file From 218f9abfb6fe3ed3178950c1be49dcf03f84c3b3 Mon Sep 17 00:00:00 2001 From: WaldiS Date: Thu, 5 Nov 2020 19:19:08 +0000 Subject: [PATCH 094/106] Translated using Weblate (Polish) Currently translated at 99.3% (3501 of 3524 strings) --- OsmAnd/res/values-pl/strings.xml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/OsmAnd/res/values-pl/strings.xml b/OsmAnd/res/values-pl/strings.xml index a523ac90ad..19ad8d4b91 100644 --- a/OsmAnd/res/values-pl/strings.xml +++ b/OsmAnd/res/values-pl/strings.xml @@ -3913,7 +3913,7 @@ Nazwa: A – Z Co nowego Ikony start/koniec - Dziękujemy za zakup linii konturowych + Dziękujemy za zakup \"Linii konturowych\" Subskrypcja naliczona za wybrany okres. Anuluj ją w AppGallery w dowolnym momencie. Płatność zostanie pobrana z konta AppGallery po potwierdzeniu zakupu. \n @@ -3937,4 +3937,19 @@ %1$s — %2$s MGRS MGRS + Użyj 2-fazowego algorytmu routingu A * + Wykres + %1$s dane dostępne tylko na drogach, aby je uzyskać, musisz obliczyć trasę za pomocą opcji „Trasa między punktami”. + Poczekaj na ponowne obliczenie trasy. +\nWykres będzie dostępny po ponownym obliczeniu. + Mapy lokalne + Luka + Przyjemności + Specjalne + Transport + Usługi + Symbole + Sport + Służby ratunkowe + Podróże \ No newline at end of file From 2bcc2e6559251f6965399ddecbbcb82e49adacc5 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 4 Nov 2020 21:11:32 +0000 Subject: [PATCH 095/106] Translated using Weblate (Russian) Currently translated at 99.8% (3520 of 3524 strings) --- OsmAnd/res/values-ru/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index ef0b614441..d873a03ba5 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -3937,4 +3937,8 @@ Спорт Экстренные службы Путешествие + MGRS + MGRS + OsmAnd использует MGRS, который похож на формат UTM NATO. + Развитие местного общественного транспорта \ No newline at end of file From fe87d486ffcae8f97efd60d43c86cdeee059318a Mon Sep 17 00:00:00 2001 From: Mirco Zorzo Date: Wed, 4 Nov 2020 19:03:30 +0000 Subject: [PATCH 096/106] Translated using Weblate (Italian) Currently translated at 89.7% (3162 of 3524 strings) --- OsmAnd/res/values-it/strings.xml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml index db30024603..33315de637 100644 --- a/OsmAnd/res/values-it/strings.xml +++ b/OsmAnd/res/values-it/strings.xml @@ -222,7 +222,7 @@ La versione dell\'indice \'\'{0}\'\' non è supportata Il routing offline di OsmAnd è sperimentale e non funziona per distanze superiori ai 20 km. \n -\nNavigazione eseguita temporaneamente tramite servizio online CloudMade. +\nNavigazione temporaneamente spostata sul servizio online CloudMade. Impossibile trovare la cartella specificata. Cartella salvataggio dei dati Tutti i dati offline nella vecchia app verranno supportati dalla nuova, ma i Preferiti devono essere esportati dalla vecchia app e importati nella nuova. @@ -313,13 +313,13 @@ GPS secondi min. - Intervallo di tempo di risveglio usato dal servizio in background: + Intervallo di risveglio usato dal servizio in background: Intervallo di risveglio GPS - Fornitore di posizione utilizzato dal servizio in background: + Metodo di localizzazione utilizzato dal servizio in background: Fornitore di posizionamento Traccia la posizione mentre lo schermo è spento. Esegui OsmAnd in background - Il servizio di navigazione in background di OsmAnd necessita del sistema di posizionamento attivato. + Il servizio di navigazione in background necessita di un sistema di posizionamento attivo. Nascondi filtro Visualizza filtro Filtro @@ -2695,13 +2695,13 @@ Sto cercando l’articolo Wiki corrispondente Articolo non trovato Come aprire gli articoli di Wikipedia? - Navigazione -\n • Funziona online (veloce) o offline (nessuna tariffa di roaming quando sei all\'estero) -\n • Guida vocale svolta-dopo-svolta (voci registrate e sintetizzate) -\n • Guida sulla corsia opzionale, visualizzazione dei nomi delle strade, e tempo di arrivo stimato -\n • Supporto per punti intermedi del tuo itinerario -\n • Rielaborazione del percorso automatico ogni volta che si devia -\n • Ricerca di posti per indirizzo, per tipo (es: ristorante, albergo, stazione di servizio, museo) o per coordinate geografiche + Navigazione +\n • Funziona online (veloce) o offline (nessuna tariffa di roaming quando sei all\'estero) +\n • Guida vocale svolta-per-svolta (voci registrate e sintetizzate) +\n • Indicazioni di corsia opzionali, visualizzazione dei nomi delle strade, e tempo di arrivo stimato +\n • Supporto dei punti intermedi del tuo itinerario +\n • Rielaborazione del percorso automatico ogni volta che si devia +\n • Ricerca di luoghi per indirizzo, per tipo (es: ristorante, albergo, stazione di servizio, museo) o per coordinate geografiche \n Nascondi la descrizione completa Mostra la descrizione completa @@ -2743,12 +2743,12 @@ \n • Condividi la tua posizione in modo tale che i tuoi amici possano trovarti \n Funzioni per pedoni e velocipedi -\n • Mostra percorsi per pedoni, escursionisti e biciclette, ottimo per le attività all’aperto +\n • Mostra percorsi per pedoni, escursionisti e biciclette, ottimo per le attività all\'aperto \n • Navigazione e visualizzazione speciali per pedoni e velocipedi \n • Scegli se mostrare le fermate del trasporto pubblico (bus, tram e treno) inclusi i nomi delle linee \n • Scegli se registrare la tua visita su un file GPX locale oppure su di un servizio online \n • Scegli se mostrare la velocità e l’altitudine -\n • Mostra le curve di livello e l’ombreggiatura dei rilievi +\n • Mostra le curve di livello e l’ombreggiatura dei rilievi (attraverso il componente aggiuntivo) Modifica dello stile standard per un maggior contrasto delle strade pedonali e piste ciclabili. Utilizza i colori della versione vecchia di Mapnik. Orario di arrivo intermedio Orario intermedio @@ -3940,7 +3940,7 @@ Amenità Speciale Trasporto - Servizio + Servizi Simboli Sport Emergenza From 8ec94b7ae249d231ec2d43e22bc6b4eb48693efa Mon Sep 17 00:00:00 2001 From: Michal L Date: Thu, 5 Nov 2020 22:08:54 +0000 Subject: [PATCH 097/106] Translated using Weblate (Polish) Currently translated at 99.3% (3502 of 3524 strings) --- OsmAnd/res/values-pl/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/res/values-pl/strings.xml b/OsmAnd/res/values-pl/strings.xml index 19ad8d4b91..274f6b544a 100644 --- a/OsmAnd/res/values-pl/strings.xml +++ b/OsmAnd/res/values-pl/strings.xml @@ -3944,7 +3944,7 @@ \nWykres będzie dostępny po ponownym obliczeniu. Mapy lokalne Luka - Przyjemności + Udogodnienie Specjalne Transport Usługi From d3dd9ef3233cda28088cf0ece734c497a316a0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=BB=D0=B0=D0=BC=D0=B5=D0=BD?= Date: Thu, 5 Nov 2020 12:38:26 +0000 Subject: [PATCH 098/106] Translated using Weblate (Bulgarian) Currently translated at 47.6% (1680 of 3524 strings) --- OsmAnd/res/values-bg/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OsmAnd/res/values-bg/strings.xml b/OsmAnd/res/values-bg/strings.xml index 35f42cfdcc..f225fb42df 100644 --- a/OsmAnd/res/values-bg/strings.xml +++ b/OsmAnd/res/values-bg/strings.xml @@ -2218,4 +2218,10 @@ Всички предишни сегменти Само избраният сегмент ще бъде преизчислен съобразно избрания профил. Всички следващи сегменти ще бъдат преизчислени с помощта на избрания профил. + Промяна типа на маршрута след + Опростена пътека + Само линията на маршрута ще бъде запазена, точките ще бъдат изтрити. + Име на файл + Избрани файлове за проследяване: %s + REC \ No newline at end of file From bd08933ca41cf41cd0ba3618e6e3a0bd94c5b367 Mon Sep 17 00:00:00 2001 From: ssantos Date: Thu, 5 Nov 2020 07:43:27 +0000 Subject: [PATCH 099/106] Translated using Weblate (Portuguese) Currently translated at 100.0% (3830 of 3830 strings) --- OsmAnd/res/values-pt/phrases.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OsmAnd/res/values-pt/phrases.xml b/OsmAnd/res/values-pt/phrases.xml index 978eb601ae..2386f2f08a 100644 --- a/OsmAnd/res/values-pt/phrases.xml +++ b/OsmAnd/res/values-pt/phrases.xml @@ -3833,4 +3833,6 @@ Barracão Telhado Ponto GPX + Torre de radar + Área de repouso \ No newline at end of file From 22cf3249aca94aa6ba61d3db0bf429776fa52bc8 Mon Sep 17 00:00:00 2001 From: Ahmed744 Date: Wed, 4 Nov 2020 23:07:39 +0000 Subject: [PATCH 100/106] Translated using Weblate (Arabic (Saudi Arabia)) Currently translated at 100.0% (271 of 271 strings) Translation: OsmAnd/Telegram Translate-URL: https://hosted.weblate.org/projects/osmand/telegram/ar_SA/ --- OsmAnd-telegram/res/values-ar-rSA/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OsmAnd-telegram/res/values-ar-rSA/strings.xml b/OsmAnd-telegram/res/values-ar-rSA/strings.xml index da6f0efd1b..f799745114 100644 --- a/OsmAnd-telegram/res/values-ar-rSA/strings.xml +++ b/OsmAnd-telegram/res/values-ar-rSA/strings.xml @@ -267,4 +267,8 @@ مشاركة: %1$s مفعل %1$s منذ + تصدير + لوجكات العازلة + تحقق من السجلات التفصيلية للتطبيق وشاركها + إرسال تقرير \ No newline at end of file From 87a165ee31476d3b4de0d65c2599ed7f5bf5e9b5 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 4 Nov 2020 21:10:06 +0000 Subject: [PATCH 101/106] Translated using Weblate (Russian) Currently translated at 99.9% (3828 of 3830 strings) --- OsmAnd/res/values-ru/phrases.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values-ru/phrases.xml b/OsmAnd/res/values-ru/phrases.xml index 36b7e66d59..c75c0ac4ef 100644 --- a/OsmAnd/res/values-ru/phrases.xml +++ b/OsmAnd/res/values-ru/phrases.xml @@ -3835,4 +3835,5 @@ СПГ Навесы Точка GPX + Радиолокационная вышка \ No newline at end of file From 5f45b8751f3d657c2c5032424df126afb104661d Mon Sep 17 00:00:00 2001 From: max-klaus Date: Fri, 6 Nov 2020 13:17:40 +0300 Subject: [PATCH 102/106] Handle subscription states (on hold / paused) --- ...t.xml => osmlive_gone_dialog_fragment.xml} | 17 +- OsmAnd/res/values/strings.xml | 5 + .../plus/inapp/InAppPurchaseHelperImpl.java | 56 ++- OsmAnd/src/net/osmand/plus/Version.java | 4 +- .../osmand/plus/activities/MapActivity.java | 7 +- .../chooseplan/OsmLiveCancelledDialog.java | 245 ------------- .../plus/chooseplan/OsmLiveGoneDialog.java | 334 ++++++++++++++++++ .../plus/inapp/InAppPurchaseHelper.java | 57 ++- .../net/osmand/plus/inapp/InAppPurchases.java | 86 +++++ .../plus/settings/backend/OsmandSettings.java | 5 +- 10 files changed, 514 insertions(+), 302 deletions(-) rename OsmAnd/res/layout/{osmlive_cancelled_dialog_fragment.xml => osmlive_gone_dialog_fragment.xml} (81%) delete mode 100644 OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveCancelledDialog.java create mode 100644 OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveGoneDialog.java diff --git a/OsmAnd/res/layout/osmlive_cancelled_dialog_fragment.xml b/OsmAnd/res/layout/osmlive_gone_dialog_fragment.xml similarity index 81% rename from OsmAnd/res/layout/osmlive_cancelled_dialog_fragment.xml rename to OsmAnd/res/layout/osmlive_gone_dialog_fragment.xml index a936b85350..1a2a28f1c6 100644 --- a/OsmAnd/res/layout/osmlive_cancelled_dialog_fragment.xml +++ b/OsmAnd/res/layout/osmlive_gone_dialog_fragment.xml @@ -84,26 +84,11 @@ - - + android:layout_marginTop="@dimen/title_padding"> diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 91eec18222..c0d8bb8721 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,11 @@ Thx - Hardy --> + OsmAnd Live subscription is on hold + OsmAnd Live subscription has been paused + OsmAnd Live subscription has been expired + There is a problem with your subscription. Click the button to go to the Google Play subscription settings to fix your payment method. + Manage subscription You must add at least two points. Travel Emergency diff --git a/OsmAnd/src-google/net/osmand/plus/inapp/InAppPurchaseHelperImpl.java b/OsmAnd/src-google/net/osmand/plus/inapp/InAppPurchaseHelperImpl.java index 5bd9f2cb23..d5ff6fcedf 100644 --- a/OsmAnd/src-google/net/osmand/plus/inapp/InAppPurchaseHelperImpl.java +++ b/OsmAnd/src-google/net/osmand/plus/inapp/InAppPurchaseHelperImpl.java @@ -21,8 +21,10 @@ import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.inapp.InAppPurchases.InAppPurchase; import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription.SubscriptionState; import net.osmand.plus.inapp.InAppPurchasesImpl.InAppPurchaseLiveUpdatesOldSubscription; import net.osmand.plus.inapp.util.BillingManager; +import net.osmand.plus.settings.backend.CommonPreference; import net.osmand.plus.settings.backend.OsmandPreference; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.srtmplugin.SRTMPlugin; @@ -33,6 +35,7 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map.Entry; public class InAppPurchaseHelperImpl extends InAppPurchaseHelper { @@ -139,6 +142,7 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper { for (Purchase p : purchases) { skuSubscriptions.add(p.getSku()); } + skuSubscriptions.addAll(subscriptionStateMap.keySet()); BillingManager billingManager = getBillingManager(); // Have we been disposed of in the meantime? If so, quit. @@ -291,7 +295,7 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper { } // Listener that's called when we finish querying the items and subscriptions we own - private SkuDetailsResponseListener mSkuDetailsResponseListener = new SkuDetailsResponseListener() { + private final SkuDetailsResponseListener mSkuDetailsResponseListener = new SkuDetailsResponseListener() { @NonNull private List getAllOwnedSubscriptionSkus() { @@ -304,6 +308,15 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper { } } } + for (Entry entry : subscriptionStateMap.entrySet()) { + SubscriptionState state = entry.getValue(); + if (state == SubscriptionState.PAUSED || state == SubscriptionState.ON_HOLD) { + String sku = entry.getKey(); + if (!result.contains(sku)) { + result.add(sku); + } + } + } return result; } @@ -399,35 +412,28 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper { // Do we have the live updates? boolean subscribedToLiveUpdates = false; List liveUpdatesPurchases = new ArrayList<>(); - for (InAppPurchase p : getLiveUpdates().getAllSubscriptions()) { - Purchase purchase = getPurchase(p.getSku()); - if (purchase != null) { - liveUpdatesPurchases.add(purchase); + for (InAppSubscription s : getLiveUpdates().getAllSubscriptions()) { + Purchase purchase = getPurchase(s.getSku()); + if (purchase != null || s.getState().isActive()) { + if (purchase != null) { + liveUpdatesPurchases.add(purchase); + } if (!subscribedToLiveUpdates) { subscribedToLiveUpdates = true; } } } - OsmandPreference subscriptionCancelledTime = ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_TIME; if (!subscribedToLiveUpdates && ctx.getSettings().LIVE_UPDATES_PURCHASED.get()) { - if (subscriptionCancelledTime.get() == 0) { - subscriptionCancelledTime.set(System.currentTimeMillis()); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN.set(false); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN.set(false); - } else if (System.currentTimeMillis() - subscriptionCancelledTime.get() > SUBSCRIPTION_HOLDING_TIME_MSEC) { - ctx.getSettings().LIVE_UPDATES_PURCHASED.set(false); - if (!isDepthContoursPurchased(ctx)) { - ctx.getSettings().getCustomRenderBooleanProperty("depthContours").set(false); - } + ctx.getSettings().LIVE_UPDATES_PURCHASED.set(false); + if (!isDepthContoursPurchased(ctx)) { + ctx.getSettings().getCustomRenderBooleanProperty("depthContours").set(false); } } else if (subscribedToLiveUpdates) { - subscriptionCancelledTime.set(0L); ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true); } lastValidationCheckTime = System.currentTimeMillis(); - logDebug("User " + (subscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE") - + " live updates purchased."); + logDebug("User " + (subscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE") + " live updates purchased."); OsmandSettings settings = ctx.getSettings(); settings.INAPPS_READ.set(true); @@ -490,12 +496,24 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper { } } if (inAppPurchase instanceof InAppSubscription) { + InAppSubscription s = (InAppSubscription) inAppPurchase; + + SubscriptionState state = subscriptionStateMap.get(inAppPurchase.getSku()); + s.setState(state == null ? SubscriptionState.UNDEFINED : state); + CommonPreference statePref = ctx.getSettings().registerStringPreference( + s.getSku() + "_state", SubscriptionState.UNDEFINED.getStateStr()).makeGlobal(); + s.setPrevState(SubscriptionState.getByStateStr(statePref.get())); + statePref.set(s.getState().getStateStr()); + if (s.getState().isGone() && s.hasStateChanged()) { + ctx.getSettings().LIVE_UPDATES_EXPIRED_FIRST_DLG_SHOWN_TIME.set(0L); + ctx.getSettings().LIVE_UPDATES_EXPIRED_SECOND_DLG_SHOWN_TIME.set(0L); + } + String introductoryPrice = skuDetails.getIntroductoryPrice(); String introductoryPricePeriod = skuDetails.getIntroductoryPricePeriod(); String introductoryPriceCycles = skuDetails.getIntroductoryPriceCycles(); long introductoryPriceAmountMicros = skuDetails.getIntroductoryPriceAmountMicros(); if (!Algorithms.isEmpty(introductoryPrice)) { - InAppSubscription s = (InAppSubscription) inAppPurchase; try { s.setIntroductoryInfo(new InAppPurchases.InAppSubscriptionIntroductoryInfo(s, introductoryPrice, introductoryPriceAmountMicros, introductoryPricePeriod, introductoryPriceCycles)); diff --git a/OsmAnd/src/net/osmand/plus/Version.java b/OsmAnd/src/net/osmand/plus/Version.java index 48dd9b1feb..8e23518613 100644 --- a/OsmAnd/src/net/osmand/plus/Version.java +++ b/OsmAnd/src/net/osmand/plus/Version.java @@ -134,11 +134,11 @@ public class Version { } public static boolean isDeveloperVersion(OsmandApplication ctx){ - return getAppName(ctx).contains("~") || ctx.getPackageName().equals(FREE_DEV_VERSION_NAME); + return false;//getAppName(ctx).contains("~") || ctx.getPackageName().equals(FREE_DEV_VERSION_NAME); } public static boolean isDeveloperBuild(OsmandApplication ctx){ - return getAppName(ctx).contains("~"); + return false;//getAppName(ctx).contains("~"); } public static String getVersionForTracker(OsmandApplication ctx) { diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index 8cb6e832c5..2d33be5f82 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -83,7 +83,7 @@ import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.base.ContextMenuFragment; import net.osmand.plus.base.FailSafeFuntions; import net.osmand.plus.base.MapViewTrackingUtilities; -import net.osmand.plus.chooseplan.OsmLiveCancelledDialog; +import net.osmand.plus.chooseplan.OsmLiveGoneDialog; import net.osmand.plus.dashboard.DashBaseFragment; import net.osmand.plus.dashboard.DashboardOnMap; import net.osmand.plus.dialogs.CrashBottomSheetDialogFragment; @@ -845,8 +845,6 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven getSupportFragmentManager().beginTransaction() .add(R.id.fragmentContainer, new FirstUsageWelcomeFragment(), FirstUsageWelcomeFragment.TAG).commitAllowingStateLoss(); - } else if (!isFirstScreenShowing() && OsmLiveCancelledDialog.shouldShowDialog(app)) { - OsmLiveCancelledDialog.showInstance(getSupportFragmentManager()); } else if (SendAnalyticsBottomSheetDialogFragment.shouldShowDialog(app)) { SendAnalyticsBottomSheetDialogFragment.showInstance(app, getSupportFragmentManager(), null); } @@ -2290,6 +2288,9 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven @Override public void onInAppPurchaseGetItems() { DiscountHelper.checkAndDisplay(this); + if (!isFirstScreenShowing() && OsmLiveGoneDialog.shouldShowDialog(app)) { + OsmLiveGoneDialog.showInstance(app, getSupportFragmentManager()); + } } public enum ShowQuickSearchMode { diff --git a/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveCancelledDialog.java b/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveCancelledDialog.java deleted file mode 100644 index a62ffcd296..0000000000 --- a/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveCancelledDialog.java +++ /dev/null @@ -1,245 +0,0 @@ -package net.osmand.plus.chooseplan; - -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.os.Build; -import android.os.Bundle; -import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.widget.ProgressBar; - -import androidx.annotation.ColorRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - -import net.osmand.PlatformUtil; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.Version; -import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.settings.backend.OsmandPreference; -import net.osmand.plus.R; -import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.base.BaseOsmAndDialogFragment; -import net.osmand.plus.chooseplan.ChoosePlanDialogFragment.OsmAndFeature; -import net.osmand.plus.inapp.InAppPurchaseHelper; -import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; -import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; -import net.osmand.plus.widgets.TextViewEx; - -import org.apache.commons.logging.Log; - -import static net.osmand.plus.inapp.InAppPurchaseHelper.SUBSCRIPTION_HOLDING_TIME_MSEC; - -public class OsmLiveCancelledDialog extends BaseOsmAndDialogFragment implements InAppPurchaseListener { - public static final String TAG = OsmLiveCancelledDialog.class.getSimpleName(); - private static final Log LOG = PlatformUtil.getLog(OsmLiveCancelledDialog.class); - - private OsmandApplication app; - private InAppPurchaseHelper purchaseHelper; - - private boolean nightMode; - private View osmLiveButton; - - private final OsmAndFeature[] osmLiveFeatures = { - OsmAndFeature.DAILY_MAP_UPDATES, - OsmAndFeature.UNLIMITED_DOWNLOADS, - OsmAndFeature.WIKIPEDIA_OFFLINE, - OsmAndFeature.WIKIVOYAGE_OFFLINE, - OsmAndFeature.CONTOUR_LINES_HILLSHADE_MAPS, - OsmAndFeature.SEA_DEPTH_MAPS, - OsmAndFeature.UNLOCK_ALL_FEATURES, - }; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - app = getMyApplication(); - purchaseHelper = app.getInAppPurchaseHelper(); - nightMode = isNightMode(getMapActivity() != null); - } - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - Activity ctx = requireActivity(); - int themeId = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar; - Dialog dialog = new Dialog(ctx, themeId); - Window window = dialog.getWindow(); - if (window != null) { - window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - if (!getSettings().DO_NOT_USE_ANIMATIONS.get()) { - window.getAttributes().windowAnimations = R.style.Animations_Alpha; - } - if (Build.VERSION.SDK_INT >= 21) { - window.setStatusBarColor(ContextCompat.getColor(ctx, getStatusBarColor())); - } - } - return dialog; - } - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - Context ctx = getContext(); - if (ctx == null) { - return null; - } - int themeRes = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar; - View view = LayoutInflater.from(new ContextThemeWrapper(getContext(), themeRes)) - .inflate(R.layout.osmlive_cancelled_dialog_fragment, container, false); - - view.findViewById(R.id.button_close).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - dismiss(); - } - }); - - TextViewEx infoDescr = (TextViewEx) view.findViewById(R.id.info_description); - StringBuilder descr = new StringBuilder(); - descr.append(getString(R.string.purchase_cancelled_dialog_descr)); - for (OsmAndFeature feature : osmLiveFeatures) { - descr.append("\n").append("— ").append(feature.toHumanString(ctx)); - } - infoDescr.setText(descr); - TextViewEx inappDescr = (TextViewEx) view.findViewById(R.id.inapp_descr); - inappDescr.setText(Version.isHuawei(app) ? R.string.osm_live_payment_desc_hw : R.string.osm_live_payment_desc); - - osmLiveButton = view.findViewById(R.id.card_button); - - return view; - } - - @Nullable - public MapActivity getMapActivity() { - Activity activity = getActivity(); - if (activity instanceof MapActivity) { - return (MapActivity) activity; - } - return null; - } - - @Override - public void onResume() { - super.onResume(); - - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.disableDrawer(); - } - - boolean requestingInventory = purchaseHelper != null && purchaseHelper.getActiveTask() == InAppPurchaseTaskType.REQUEST_INVENTORY; - setupOsmLiveButton(requestingInventory); - - OsmandPreference firstTimeShown = app.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN; - OsmandPreference secondTimeShown = app.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN; - if (!firstTimeShown.get()) { - firstTimeShown.set(true); - } else if (!secondTimeShown.get()) { - secondTimeShown.set(true); - } - } - - @Override - public void onPause() { - super.onPause(); - - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.enableDrawer(); - } - } - - @ColorRes - protected int getStatusBarColor() { - return nightMode ? R.color.status_bar_wikivoyage_dark : R.color.status_bar_wikivoyage_light; - } - - @Override - public void onError(InAppPurchaseTaskType taskType, String error) { - if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { - setupOsmLiveButton(false); - } - } - - @Override - public void onGetItems() { - } - - @Override - public void onItemPurchased(String sku, boolean active) { - } - - @Override - public void showProgress(InAppPurchaseTaskType taskType) { - if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { - setupOsmLiveButton(true); - } - } - - @Override - public void dismissProgress(InAppPurchaseTaskType taskType) { - if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { - setupOsmLiveButton(false); - } - } - - private void setupOsmLiveButton(boolean progress) { - if (osmLiveButton != null) { - ProgressBar progressBar = (ProgressBar) osmLiveButton.findViewById(R.id.card_button_progress); - TextViewEx buttonTitle = (TextViewEx) osmLiveButton.findViewById(R.id.card_button_title); - TextViewEx buttonSubtitle = (TextViewEx) osmLiveButton.findViewById(R.id.card_button_subtitle); - buttonTitle.setText(getString(R.string.osm_live_plan_pricing)); - buttonSubtitle.setVisibility(View.GONE); - if (progress) { - buttonTitle.setVisibility(View.GONE); - progressBar.setVisibility(View.VISIBLE); - osmLiveButton.setOnClickListener(null); - } else { - buttonTitle.setVisibility(View.VISIBLE); - progressBar.setVisibility(View.GONE); - osmLiveButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - dismiss(); - FragmentActivity activity = getActivity(); - if (activity != null) { - ChoosePlanDialogFragment.showOsmLiveInstance(activity.getSupportFragmentManager()); - } - } - }); - } - } - } - - public static boolean shouldShowDialog(OsmandApplication app) { - OsmandSettings settings = app.getSettings(); - long cancelledTime = settings.LIVE_UPDATES_PURCHASE_CANCELLED_TIME.get(); - boolean firstTimeShown = settings.LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN.get(); - boolean secondTimeShown = settings.LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN.get(); - return cancelledTime > 0 - && (!firstTimeShown - || (System.currentTimeMillis() - cancelledTime > SUBSCRIPTION_HOLDING_TIME_MSEC - && !secondTimeShown)); - } - - public static void showInstance(@NonNull FragmentManager fm) { - try { - if (fm.findFragmentByTag(OsmLiveCancelledDialog.TAG) == null) { - OsmLiveCancelledDialog fragment = new OsmLiveCancelledDialog(); - fragment.show(fm, OsmLiveCancelledDialog.TAG); - } - } catch (RuntimeException e) { - LOG.error("showInstance", e); - } - } -} diff --git a/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveGoneDialog.java b/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveGoneDialog.java new file mode 100644 index 0000000000..fdbce9a076 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveGoneDialog.java @@ -0,0 +1,334 @@ +package net.osmand.plus.chooseplan; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; + +import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.BaseOsmAndDialogFragment; +import net.osmand.plus.chooseplan.ChoosePlanDialogFragment.OsmAndFeature; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; +import net.osmand.plus.settings.backend.OsmandPreference; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.widgets.TextViewEx; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; + +public abstract class OsmLiveGoneDialog extends BaseOsmAndDialogFragment { + public static final String TAG = OsmLiveGoneDialog.class.getName(); + private static final Log LOG = PlatformUtil.getLog(OsmLiveGoneDialog.class); + + private static final long TIME_BETWEEN_DIALOGS_MSEC = 1000 * 60 * 60 * 24 * 3; // 3 days + + private OsmandApplication app; + private boolean nightMode; + private View osmLiveButton; + + private final OsmAndFeature[] osmLiveFeatures = { + OsmAndFeature.DAILY_MAP_UPDATES, + OsmAndFeature.UNLIMITED_DOWNLOADS, + OsmAndFeature.WIKIPEDIA_OFFLINE, + OsmAndFeature.WIKIVOYAGE_OFFLINE, + OsmAndFeature.CONTOUR_LINES_HILLSHADE_MAPS, + OsmAndFeature.SEA_DEPTH_MAPS, + OsmAndFeature.UNLOCK_ALL_FEATURES, + }; + + public static class OsmLiveOnHoldDialog extends OsmLiveGoneDialog { + public static final String TAG = OsmLiveOnHoldDialog.class.getSimpleName(); + + @Override + protected OsmLiveButtonType getOsmLiveButtonType() { + return OsmLiveButtonType.MANAGE_SUBSCRIPTION; + } + + @Override + protected String getTitle() { + return getString(R.string.subscription_on_hold_title); + } + + @Override + protected String getSubscriptionDescr() { + return getString(R.string.subscription_payment_issue_title); + } + } + + public static class OsmLivePausedDialog extends OsmLiveGoneDialog { + public static final String TAG = OsmLivePausedDialog.class.getSimpleName(); + + @Override + protected OsmLiveButtonType getOsmLiveButtonType() { + return OsmLiveButtonType.MANAGE_SUBSCRIPTION; + } + + @Override + protected String getTitle() { + return getString(R.string.subscription_paused_title); + } + } + + public static class OsmLiveExpiredDialog extends OsmLiveGoneDialog { + public static final String TAG = OsmLiveExpiredDialog.class.getSimpleName(); + + @Override + protected String getTitle() { + return getString(R.string.subscription_expired_title); + } + } + + protected enum OsmLiveButtonType { + PURCHASE_SUBSCRIPTION, + MANAGE_SUBSCRIPTION + } + + protected OsmLiveButtonType getOsmLiveButtonType() { + return OsmLiveButtonType.PURCHASE_SUBSCRIPTION; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + app = getMyApplication(); + nightMode = isNightMode(getMapActivity() != null); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Activity ctx = requireActivity(); + int themeId = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar; + Dialog dialog = new Dialog(ctx, themeId); + Window window = dialog.getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + if (!getSettings().DO_NOT_USE_ANIMATIONS.get()) { + window.getAttributes().windowAnimations = R.style.Animations_Alpha; + } + if (Build.VERSION.SDK_INT >= 21) { + window.setStatusBarColor(ContextCompat.getColor(ctx, getStatusBarColor())); + } + } + return dialog; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + Context ctx = getContext(); + if (ctx == null) { + return null; + } + int themeRes = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar; + View view = LayoutInflater.from(new ContextThemeWrapper(getContext(), themeRes)) + .inflate(R.layout.osmlive_gone_dialog_fragment, container, false); + + view.findViewById(R.id.button_close).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + TextViewEx title = (TextViewEx) view.findViewById(R.id.title); + title.setText(getTitle()); + TextViewEx infoDescr = (TextViewEx) view.findViewById(R.id.info_description); + StringBuilder descr = new StringBuilder(); + String subscriptionDescr = getSubscriptionDescr(); + if (!Algorithms.isEmpty(subscriptionDescr)) { + descr.append(subscriptionDescr).append("\n\n"); + } + descr.append(getString(R.string.purchase_cancelled_dialog_descr)); + for (OsmAndFeature feature : osmLiveFeatures) { + descr.append("\n").append("— ").append(feature.toHumanString(ctx)); + } + infoDescr.setText(descr); + + osmLiveButton = view.findViewById(R.id.card_button); + + return view; + } + + protected abstract String getTitle(); + + protected String getSubscriptionDescr() { + return null; + } + + @Nullable + public MapActivity getMapActivity() { + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + return (MapActivity) activity; + } + return null; + } + + @Override + public void onResume() { + super.onResume(); + + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.disableDrawer(); + } + + setupOsmLiveButton(); + + OsmandPreference firstTimeShownTime = app.getSettings().LIVE_UPDATES_EXPIRED_FIRST_DLG_SHOWN_TIME; + OsmandPreference secondTimeShownTime = app.getSettings().LIVE_UPDATES_EXPIRED_SECOND_DLG_SHOWN_TIME; + if (firstTimeShownTime.get() == 0) { + firstTimeShownTime.set(System.currentTimeMillis()); + } else if (secondTimeShownTime.get() == 0) { + secondTimeShownTime.set(System.currentTimeMillis()); + } + } + + @Override + public void onPause() { + super.onPause(); + + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.enableDrawer(); + } + } + + @ColorRes + protected int getStatusBarColor() { + return nightMode ? R.color.status_bar_wikivoyage_dark : R.color.status_bar_wikivoyage_light; + } + + private void setupOsmLiveButton() { + if (osmLiveButton != null) { + TextViewEx buttonTitle = (TextViewEx) osmLiveButton.findViewById(R.id.card_button_title); + TextViewEx buttonSubtitle = (TextViewEx) osmLiveButton.findViewById(R.id.card_button_subtitle); + switch (getOsmLiveButtonType()) { + case PURCHASE_SUBSCRIPTION: + buttonTitle.setText(getString(R.string.osm_live_plan_pricing)); + osmLiveButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + FragmentActivity activity = getActivity(); + if (activity != null) { + ChoosePlanDialogFragment.showOsmLiveInstance(activity.getSupportFragmentManager()); + } + } + }); + break; + case MANAGE_SUBSCRIPTION: + buttonTitle.setText(getString(R.string.manage_subscription)); + osmLiveButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + FragmentActivity activity = getActivity(); + if (activity != null) { + InAppSubscription expiredSubscription = getExpiredSubscription((OsmandApplication) activity.getApplication()); + if (expiredSubscription != null) { + manageSubscription(expiredSubscription.getSku()); + } + } + } + }); + break; + } + buttonSubtitle.setVisibility(View.GONE); + buttonTitle.setVisibility(View.VISIBLE); + osmLiveButton.findViewById(R.id.card_button_progress).setVisibility(View.GONE); + } + } + + private void manageSubscription(@Nullable String sku) { + Context ctx = getContext(); + if (ctx != null) { + String url = "https://play.google.com/store/account/subscriptions?package=" + ctx.getPackageName(); + if (!Algorithms.isEmpty(sku)) { + url += "&sku=" + sku; + } + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(intent); + } + } + + @Nullable + private static InAppSubscription getExpiredSubscription(@NonNull OsmandApplication app) { + if (!app.getSettings().LIVE_UPDATES_PURCHASED.get()) { + InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); + return purchaseHelper.getLiveUpdates().getTopExpiredSubscription(); + } + return null; + } + + public static boolean shouldShowDialog(@NonNull OsmandApplication app) { + InAppSubscription expiredSubscription = getExpiredSubscription(app); + if (expiredSubscription == null) { + return false; + } + OsmandSettings settings = app.getSettings(); + long firstTimeShownTime = settings.LIVE_UPDATES_EXPIRED_FIRST_DLG_SHOWN_TIME.get(); + long secondTimeShownTime = settings.LIVE_UPDATES_EXPIRED_SECOND_DLG_SHOWN_TIME.get(); + return firstTimeShownTime == 0 + || (System.currentTimeMillis() - firstTimeShownTime > TIME_BETWEEN_DIALOGS_MSEC && secondTimeShownTime == 0); + } + + public static void showInstance(@NonNull OsmandApplication app, @NonNull FragmentManager fm) { + try { + InAppSubscription expiredSubscription = getExpiredSubscription(app); + if (expiredSubscription == null) { + return; + } + String tag = null; + DialogFragment fragment = null; + switch (expiredSubscription.getState()) { + case ON_HOLD: + tag = OsmLiveOnHoldDialog.TAG; + if (fm.findFragmentByTag(tag) == null) { + fragment = new OsmLiveOnHoldDialog(); + } + break; + case PAUSED: + tag = OsmLivePausedDialog.TAG; + if (fm.findFragmentByTag(tag) == null) { + fragment = new OsmLivePausedDialog(); + } + break; + case EXPIRED: + tag = OsmLiveExpiredDialog.TAG; + if (fm.findFragmentByTag(tag) == null) { + fragment = new OsmLiveExpiredDialog(); + } + break; + } + if (fragment != null) { + fragment.show(fm, tag); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java index 543c3a819d..c7464c6b1f 100644 --- a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java +++ b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java @@ -17,13 +17,12 @@ import net.osmand.AndroidNetworkUtils.OnRequestsResultListener; import net.osmand.AndroidNetworkUtils.RequestResponse; import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.settings.backend.OsmandPreference; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.inapp.InAppPurchases.InAppPurchase; import net.osmand.plus.inapp.InAppPurchases.InAppPurchase.PurchaseState; import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription.SubscriptionState; import net.osmand.plus.inapp.InAppPurchases.InAppSubscriptionList; import net.osmand.plus.liveupdates.CountrySelectionFragment; import net.osmand.plus.liveupdates.CountrySelectionFragment.CountryItem; @@ -50,11 +49,10 @@ public abstract class InAppPurchaseHelper { private static final String TAG = InAppPurchaseHelper.class.getSimpleName(); private boolean mDebugLog = false; - public static final long SUBSCRIPTION_HOLDING_TIME_MSEC = 1000 * 60 * 60 * 24 * 3; // 3 days - protected InAppPurchases purchases; protected long lastValidationCheckTime; protected boolean inventoryRequested; + protected Map subscriptionStateMap = new HashMap<>(); private static final long PURCHASE_VALIDATION_PERIOD_MSEC = 1000 * 60 * 60 * 24; // daily @@ -375,21 +373,33 @@ public abstract class InAppPurchaseHelper { final String sku, final String payload) throws UnsupportedOperationException; @SuppressLint("StaticFieldLeak") - private class RequestInventoryTask extends AsyncTask { + private class RequestInventoryTask extends AsyncTask { RequestInventoryTask() { } @Override - protected String doInBackground(Void... params) { + protected String[] doInBackground(Void... params) { try { Map parameters = new HashMap<>(); parameters.put("androidPackage", ctx.getPackageName()); addUserInfo(parameters); - return AndroidNetworkUtils.sendRequest(ctx, + String activeSubscriptionsIds = AndroidNetworkUtils.sendRequest(ctx, "https://osmand.net/api/subscriptions/active", parameters, "Requesting active subscriptions...", false, false); + String subscriptionsState = null; + String userId = ctx.getSettings().BILLING_USER_ID.get(); + String userToken = ctx.getSettings().BILLING_USER_TOKEN.get(); + if (!Algorithms.isEmpty(userId) && !Algorithms.isEmpty(userToken)) { + parameters.put("userId", userId); + parameters.put("userToken", userToken); + subscriptionsState = AndroidNetworkUtils.sendRequest(ctx, + "https://osmand.net/api/subscriptions/get", + parameters, "Requesting subscriptions state...", false, false); + } + + return new String[] { activeSubscriptionsIds, subscriptionsState }; } catch (Exception e) { logError("sendRequest Error", e); } @@ -397,12 +407,14 @@ public abstract class InAppPurchaseHelper { } @Override - protected void onPostExecute(String response) { - logDebug("Response=" + response); - if (response != null) { + protected void onPostExecute(String[] response) { + logDebug("Response=" + Arrays.toString(response)); + String activeSubscriptionsIdsJson = response[0]; + String subscriptionsStateJson = response[1]; + if (activeSubscriptionsIdsJson != null) { inventoryRequested = true; try { - JSONObject obj = new JSONObject(response); + JSONObject obj = new JSONObject(activeSubscriptionsIdsJson); JSONArray names = obj.names(); if (names != null) { for (int i = 0; i < names.length(); i++) { @@ -418,6 +430,24 @@ public abstract class InAppPurchaseHelper { logError("Json parsing error", e); } } + if (subscriptionsStateJson != null) { + inventoryRequested = true; + Map subscriptionStateMap = new HashMap<>(); + try { + JSONArray subArrJson = new JSONArray(subscriptionsStateJson); + for (int i = 0; i < subArrJson.length(); i++) { + JSONObject subObj = subArrJson.getJSONObject(i); + String sku = subObj.getString("sku"); + String state = subObj.getString("state"); + if (!Algorithms.isEmpty(sku) && !Algorithms.isEmpty(state)) { + subscriptionStateMap.put(sku, SubscriptionState.getByStateStr(state)); + } + } + } catch (JSONException e) { + logError("Json parsing error", e); + } + InAppPurchaseHelper.this.subscriptionStateMap = subscriptionStateMap; + } exec(InAppPurchaseTaskType.REQUEST_INVENTORY, getRequestInventoryCommand()); } } @@ -467,9 +497,8 @@ public abstract class InAppPurchaseHelper { ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true); ctx.getSettings().getCustomRenderBooleanProperty("depthContours").set(true); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_TIME.set(0L); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN.set(false); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN.set(false); + ctx.getSettings().LIVE_UPDATES_EXPIRED_FIRST_DLG_SHOWN_TIME.set(0L); + ctx.getSettings().LIVE_UPDATES_EXPIRED_SECOND_DLG_SHOWN_TIME.set(0L); notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES); notifyItemPurchased(sku, active); diff --git a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java index 5004e97165..7cc9a8fbee 100644 --- a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java +++ b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java @@ -24,6 +24,8 @@ import java.text.NumberFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.Currency; import java.util.List; import java.util.Locale; @@ -190,6 +192,28 @@ public abstract class InAppPurchases { } return null; } + + @Nullable + public InAppSubscription getTopExpiredSubscription() { + List expiredSubscriptions = new ArrayList<>(); + for (InAppSubscription s : getAllSubscriptions()) { + if (s.getState().isGone()) { + expiredSubscriptions.add(s); + } + } + Collections.sort(expiredSubscriptions, new Comparator() { + @Override + public int compare(InAppSubscription s1, InAppSubscription s2) { + int orderS1 = s1.getState().ordinal(); + int orderS2 = s2.getState().ordinal(); + if (orderS1 != orderS2) { + return (orderS1 < orderS2) ? -1 : ((orderS1 == orderS2) ? 0 : 1); + } + return Double.compare(s1.getMonthlyPriceValue(), s2.getMonthlyPriceValue()); + } + }); + return expiredSubscriptions.isEmpty() ? null : expiredSubscriptions.get(0); + } } public abstract static class InAppPurchase { @@ -554,9 +578,49 @@ public abstract class InAppPurchases { private String subscriptionPeriodString; private Period subscriptionPeriod; private boolean upgrade = false; + private SubscriptionState state = SubscriptionState.UNDEFINED; + private SubscriptionState prevState = SubscriptionState.UNDEFINED; private InAppSubscriptionIntroductoryInfo introductoryInfo; + public enum SubscriptionState { + UNDEFINED("undefined"), + ACTIVE("active"), + CANCELLED("cancelled"), + IN_GRACE_PERIOD("in_grace_period"), + ON_HOLD("on_hold"), + PAUSED("paused"), + EXPIRED("expired"); + + private final String stateStr; + + SubscriptionState(@NonNull String stateStr) { + this.stateStr = stateStr; + } + + public String getStateStr() { + return stateStr; + } + + @NonNull + public static SubscriptionState getByStateStr(@NonNull String stateStr) { + for (SubscriptionState state : SubscriptionState.values()) { + if (state.stateStr.equals(stateStr)) { + return state; + } + } + return UNDEFINED; + } + + public boolean isGone() { + return this == ON_HOLD || this == PAUSED || this == EXPIRED; + } + + public boolean isActive() { + return this == ACTIVE || this == CANCELLED || this == IN_GRACE_PERIOD; + } + } + InAppSubscription(@NonNull String skuNoVersion, int version) { super(skuNoVersion + "_v" + version); this.skuNoVersion = skuNoVersion; @@ -592,6 +656,28 @@ public abstract class InAppPurchases { return upgrade; } + @NonNull + public SubscriptionState getState() { + return state; + } + + public void setState(@NonNull SubscriptionState state) { + this.state = state; + } + + @NonNull + public SubscriptionState getPrevState() { + return prevState; + } + + public void setPrevState(@NonNull SubscriptionState prevState) { + this.prevState = prevState; + } + + public boolean hasStateChanged() { + return state != prevState; + } + public boolean isAnyPurchased() { if (isPurchased()) { return true; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index bcc7a4c170..d24dd23ee6 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -1104,9 +1104,8 @@ public class OsmandSettings { public final OsmandPreference BILLING_PURCHASE_TOKEN_SENT = new BooleanPreference(this, "billing_purchase_token_sent", false).makeGlobal(); public final OsmandPreference BILLING_PURCHASE_TOKENS_SENT = new StringPreference(this, "billing_purchase_tokens_sent", "").makeGlobal(); public final OsmandPreference LIVE_UPDATES_PURCHASED = new BooleanPreference(this, "billing_live_updates_purchased", false).makeGlobal(); - public final OsmandPreference LIVE_UPDATES_PURCHASE_CANCELLED_TIME = new LongPreference(this, "live_updates_purchase_cancelled_time", 0).makeGlobal(); - public final OsmandPreference LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN = new BooleanPreference(this, "live_updates_purchase_cancelled_first_dlg_shown", false).makeGlobal(); - public final OsmandPreference LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN = new BooleanPreference(this, "live_updates_purchase_cancelled_second_dlg_shown", false).makeGlobal(); + public final OsmandPreference LIVE_UPDATES_EXPIRED_FIRST_DLG_SHOWN_TIME = new LongPreference(this, "live_updates_expired_first_dlg_shown_time", 0).makeGlobal(); + public final OsmandPreference LIVE_UPDATES_EXPIRED_SECOND_DLG_SHOWN_TIME = new LongPreference(this, "live_updates_expired_second_dlg_shown_time", 0).makeGlobal(); public final OsmandPreference FULL_VERSION_PURCHASED = new BooleanPreference(this, "billing_full_version_purchased", false).makeGlobal(); public final OsmandPreference DEPTH_CONTOURS_PURCHASED = new BooleanPreference(this, "billing_sea_depth_purchased", false).makeGlobal(); public final OsmandPreference CONTOUR_LINES_PURCHASED = new BooleanPreference(this, "billing_srtm_purchased", false).makeGlobal(); From e01ff6a646a54d7fdbfe3e925f1ad81d16de7d7a Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Fri, 6 Nov 2020 12:54:56 +0200 Subject: [PATCH 103/106] Fix #10091 Replacing a Favorite is faulty --- .../osmand/plus/dialogs/FavoriteDialogs.java | 25 ++++++++++++------- .../editors/PointEditorFragmentNew.java | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java b/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java index b6817fab05..e2a53f1d4a 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java @@ -20,6 +20,7 @@ import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; import net.osmand.AndroidUtils; import net.osmand.data.FavouritePoint; @@ -32,6 +33,8 @@ import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.FavoritesListFragment.FavouritesAdapter; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.mapcontextmenu.editors.FavoritePointEditor; +import net.osmand.plus.mapcontextmenu.editors.FavoritePointEditorFragmentNew; import java.text.MessageFormat; import java.util.ArrayList; @@ -79,20 +82,24 @@ public class FavoriteDialogs { @Override public void onClick(DialogInterface dialog, int which) { - if(dlgHolder != null && dlgHolder.length > 0 && dlgHolder[0] != null) { + if (dlgHolder != null && dlgHolder.length > 0 && dlgHolder[0] != null) { dlgHolder[0].dismiss(); } - FavouritePoint point = (FavouritePoint) args.getSerializable(KEY_FAVORITE); - if (helper.editFavourite(fp, point.getLatitude(), point.getLongitude())) { - helper.deleteFavourite(point); - if (activity instanceof MapActivity) { - ((MapActivity) activity).getContextMenu() + if (activity instanceof MapActivity) { + MapActivity mapActivity = (MapActivity) activity; + FavouritePoint point = (FavouritePoint) args.getSerializable(KEY_FAVORITE); + if (point != null && helper.editFavourite(fp, point.getLatitude(), point.getLongitude())) { + helper.deleteFavourite(point); + Fragment fragment = mapActivity.getSupportFragmentManager() + .findFragmentByTag(FavoritePointEditor.TAG); + if (fragment instanceof FavoritePointEditorFragmentNew) { + ((FavoritePointEditorFragmentNew) fragment).exitEditing(); + } + mapActivity.getContextMenu() .show(new LatLon(point.getLatitude(), point.getLongitude()), fp.getPointDescription(activity), fp); } + mapActivity.getMapView().refreshMap(); } - if (activity instanceof MapActivity) { - ((MapActivity) activity).getMapView().refreshMap(); - } } }); builder.show(); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java index 0918b7cd80..e59ce02373 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java @@ -942,7 +942,7 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment implemen } } - private void exitEditing() { + public void exitEditing() { cancelled = true; dismiss(); } From 9b287b81b3c8d9bea162aa532030c617788e97a4 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Fri, 6 Nov 2020 14:23:37 +0200 Subject: [PATCH 104/106] Fix #9627 Long press opens 2 menus (Local Maps) --- .../download/ui/LocalIndexesFragment.java | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java index 2fb12e2ea4..4cf4f1154a 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java @@ -7,8 +7,6 @@ import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; import android.util.TypedValue; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -19,7 +17,6 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.ExpandableListView; -import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; @@ -45,7 +42,6 @@ import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter.ItemClickListener; import net.osmand.plus.ContextMenuItem; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.SQLiteTileSource; import net.osmand.plus.UiUtilities; @@ -127,19 +123,6 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement if (asyncLoader == null || asyncLoader.getResult() == null) { reloadData(); } - - getExpandableListView().setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - long packedPos = ((ExpandableListContextMenuInfo) menuInfo).packedPosition; - int group = ExpandableListView.getPackedPositionGroup(packedPos); - int child = ExpandableListView.getPackedPositionChild(packedPos); - if (child >= 0 && group >= 0) { - final LocalIndexInfo point = listAdapter.getChild(group, child); - showContextMenu(point); - } - } - }); } public void reloadData() { @@ -156,62 +139,6 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement } } - private void showContextMenu(final LocalIndexInfo info) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - final ContextMenuAdapter adapter = new ContextMenuAdapter(getMyApplication()); - basicFileOperation(info, adapter); - OsmandPlugin.onContextMenuActivity(getActivity(), null, info, adapter); - - String[] values = adapter.getItemNames(); - builder.setItems(values, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ContextMenuItem item = adapter.getItem(which); - if (item.getItemClickListener() != null) { - item.getItemClickListener().onContextMenuClick(null, - item.getTitleId(), which, false, null); - } - } - - }); - builder.show(); - } - - private void basicFileOperation(final LocalIndexInfo info, ContextMenuAdapter adapter) { - ItemClickListener listener = new ItemClickListener() { - @Override - public boolean onContextMenuClick(ArrayAdapter adapter, int resId, int pos, boolean isChecked, int[] viewCoordinates) { - return performBasicOperation(resId, info); - } - }; - if (info.getType() == LocalIndexType.MAP_DATA || info.getType() == LocalIndexType.SRTM_DATA || - info.getType() == LocalIndexType.WIKI_DATA ) { - if (!info.isBackupedData()) { - adapter.addItem(new ContextMenuItem.ItemBuilder() - .setTitleId(R.string.local_index_mi_backup, getContext()) - .setListener(listener) - .createItem()); - } - } - if (info.isBackupedData()) { - adapter.addItem(new ContextMenuItem.ItemBuilder() - .setTitleId(R.string.local_index_mi_restore, getContext()) - .setListener(listener) - .createItem()); - } - if (info.getType() != LocalIndexType.TTS_VOICE_DATA && info.getType() != LocalIndexType.VOICE_DATA - && info.getType() != LocalIndexType.FONT_DATA) { - adapter.addItem(new ContextMenuItem.ItemBuilder() - .setTitleId(R.string.shared_string_rename, getContext()) - .setListener(listener) - .createItem()); - } - adapter.addItem(new ContextMenuItem.ItemBuilder() - .setTitleId(R.string.shared_string_delete, getContext()) - .setListener(listener) - .createItem()); - } - private boolean performBasicOperation(int resId, final LocalIndexInfo info) { if (resId == R.string.shared_string_rename) { FileUtils.renameFile(getActivity(), new File(info.getPathToData()), new RenameCallback() { From 18e231ad8b4c687b1905f555cc7285791f04fe1e Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Fri, 6 Nov 2020 15:15:41 +0200 Subject: [PATCH 105/106] Fix mapActivity --- .../net/osmand/plus/dialogs/FavoriteDialogs.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java b/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java index e2a53f1d4a..1e5e79745e 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java @@ -85,11 +85,11 @@ public class FavoriteDialogs { if (dlgHolder != null && dlgHolder.length > 0 && dlgHolder[0] != null) { dlgHolder[0].dismiss(); } - if (activity instanceof MapActivity) { - MapActivity mapActivity = (MapActivity) activity; - FavouritePoint point = (FavouritePoint) args.getSerializable(KEY_FAVORITE); - if (point != null && helper.editFavourite(fp, point.getLatitude(), point.getLongitude())) { - helper.deleteFavourite(point); + FavouritePoint point = (FavouritePoint) args.getSerializable(KEY_FAVORITE); + if (point != null && helper.editFavourite(fp, point.getLatitude(), point.getLongitude())) { + helper.deleteFavourite(point); + if (activity instanceof MapActivity) { + MapActivity mapActivity = (MapActivity) activity; Fragment fragment = mapActivity.getSupportFragmentManager() .findFragmentByTag(FavoritePointEditor.TAG); if (fragment instanceof FavoritePointEditorFragmentNew) { @@ -98,7 +98,9 @@ public class FavoriteDialogs { mapActivity.getContextMenu() .show(new LatLon(point.getLatitude(), point.getLongitude()), fp.getPointDescription(activity), fp); } - mapActivity.getMapView().refreshMap(); + if (activity instanceof MapActivity) { + ((MapActivity) activity).getMapView().refreshMap(); + } } } }); From 5732d8840eed06fdd74d92cdc96b5e43ea0c5a17 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Fri, 6 Nov 2020 15:28:55 +0200 Subject: [PATCH 106/106] Fix review --- OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java b/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java index 1e5e79745e..0690952bdd 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/FavoriteDialogs.java @@ -97,9 +97,7 @@ public class FavoriteDialogs { } mapActivity.getContextMenu() .show(new LatLon(point.getLatitude(), point.getLongitude()), fp.getPointDescription(activity), fp); - } - if (activity instanceof MapActivity) { - ((MapActivity) activity).getMapView().refreshMap(); + mapActivity.getMapView().refreshMap(); } } }