diff --git a/.github/ISSUE_TEMPLATE/5-feature-request.md b/.github/ISSUE_TEMPLATE/5-feature-request.md index 9c46069f8c..1315456d77 100644 --- a/.github/ISSUE_TEMPLATE/5-feature-request.md +++ b/.github/ISSUE_TEMPLATE/5-feature-request.md @@ -12,7 +12,7 @@ Existing issues often contain information about workarounds, resolution, or prog GitHub is our main development tool for our developers. There are hundreds of requests a month and there are relatively few developers. So by opening an issue, please know that your issue will be sent out to all developers and acknowledge that it could be closed without explanation or with just a brief message. -Comments on the closed issues are also sent to all developers, so you will definitely will be heard. +Comments on the closed issues are also sent to all developers, so you definitely will be heard. However, there is no guarantee that a developer will pick up the issue to work on it. Please be sure to read our [FAQ](https://osmand.net/help-online) before creating an issue here. diff --git a/OsmAnd-java/src/main/java/com/google/protobuf/ByteString.java b/OsmAnd-java/src/main/java/com/google/protobuf/ByteString.java index 73d831f6ee..cb1307d3b5 100644 --- a/OsmAnd-java/src/main/java/com/google/protobuf/ByteString.java +++ b/OsmAnd-java/src/main/java/com/google/protobuf/ByteString.java @@ -800,7 +800,7 @@ public abstract class ByteString implements Iterable { // Copy the information we need into local variables so as to hold // the lock for as short a time as possible. cachedFlushBuffers = - flushedBuffers.toArray(new ByteString[flushedBuffers.size()]); + flushedBuffers.toArray(new ByteString[0]); cachedBuffer = buffer; cachedBufferPos = bufferPos; } diff --git a/OsmAnd-java/src/main/java/com/google/protobuf/FieldSet.java b/OsmAnd-java/src/main/java/com/google/protobuf/FieldSet.java index 2663694fc3..02ec66309e 100644 --- a/OsmAnd-java/src/main/java/com/google/protobuf/FieldSet.java +++ b/OsmAnd-java/src/main/java/com/google/protobuf/FieldSet.java @@ -242,8 +242,7 @@ final class FieldSet nextPolyGeom = new ArrayList<>(); boolean valid = true; // Add exterior ring @@ -362,7 +361,7 @@ public final class JtsAdapter { CoordinateArrays.reverse(exteriorRing.getCoordinates()); } - nextPolyGeom.addAll(linesToGeomCmds(exteriorRing, mvtClosePath, cursor, 2)); + final List nextPolyGeom = new ArrayList<>(linesToGeomCmds(exteriorRing, mvtClosePath, cursor, 2)); // Add interior rings diff --git a/OsmAnd-java/src/main/java/com/wdtinc/mapbox_vector_tile/adapt/jts/MvtReader.java b/OsmAnd-java/src/main/java/com/wdtinc/mapbox_vector_tile/adapt/jts/MvtReader.java index 6083ca980e..73ce9eeb12 100644 --- a/OsmAnd-java/src/main/java/com/wdtinc/mapbox_vector_tile/adapt/jts/MvtReader.java +++ b/OsmAnd-java/src/main/java/com/wdtinc/mapbox_vector_tile/adapt/jts/MvtReader.java @@ -322,7 +322,7 @@ public final class MvtReader { geoms.add(geomFactory.createLineString(nextCoordSeq)); } - return geoms.size() == 1 ? geoms.get(0) : geomFactory.createMultiLineString(geoms.toArray(new LineString[geoms.size()])); + return geoms.size() == 1 ? geoms.get(0) : geomFactory.createMultiLineString(geoms.toArray(new LineString[0])); } /** @@ -450,7 +450,7 @@ public final class MvtReader { return polygons.get(0); } else { - return geomFactory.createMultiPolygon(polygons.toArray(new Polygon[polygons.size()])); + return geomFactory.createMultiPolygon(polygons.toArray(new Polygon[0])); } } @@ -512,7 +512,7 @@ public final class MvtReader { if (area > 0d) { if (outerPoly != null) { - polygons.add(geomFactory.createPolygon(outerPoly, holes.toArray(new LinearRing[holes.size()]))); + polygons.add(geomFactory.createPolygon(outerPoly, holes.toArray(new LinearRing[0]))); holes.clear(); } @@ -533,7 +533,7 @@ public final class MvtReader { if (outerPoly != null) { holes.toArray(); - polygons.add(geomFactory.createPolygon(outerPoly, holes.toArray(new LinearRing[holes.size()]))); + polygons.add(geomFactory.createPolygon(outerPoly, holes.toArray(new LinearRing[0]))); } return polygons; @@ -569,7 +569,7 @@ public final class MvtReader { if (outerPoly == null || (outerArea < 0 == area < 0)) { if (outerPoly != null) { - polygons.add(geomFactory.createPolygon(outerPoly, holes.toArray(new LinearRing[holes.size()]))); + polygons.add(geomFactory.createPolygon(outerPoly, holes.toArray(new LinearRing[0]))); holes.clear(); } @@ -590,7 +590,7 @@ public final class MvtReader { if (outerPoly != null) { holes.toArray(); - polygons.add(geomFactory.createPolygon(outerPoly, holes.toArray(new LinearRing[holes.size()]))); + polygons.add(geomFactory.createPolygon(outerPoly, holes.toArray(new LinearRing[0]))); } return polygons; diff --git a/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java b/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java index 1d1b1da020..b8835ff2c6 100644 --- a/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java +++ b/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java @@ -1247,7 +1247,7 @@ public class GPXUtilities { } } } - g.prepareInformation(fileTimestamp, splitSegments.toArray(new SplitSegment[splitSegments.size()])); + g.prepareInformation(fileTimestamp, splitSegments.toArray(new SplitSegment[0])); return g; } diff --git a/OsmAnd-java/src/main/java/net/osmand/TspHeldKarp.java b/OsmAnd-java/src/main/java/net/osmand/TspHeldKarp.java index 8c2a4baf32..e4862d3bfe 100644 --- a/OsmAnd-java/src/main/java/net/osmand/TspHeldKarp.java +++ b/OsmAnd-java/src/main/java/net/osmand/TspHeldKarp.java @@ -68,7 +68,7 @@ public class TspHeldKarp { } break; } - System.err.printf("."); + System.err.print("."); PriorityQueue children = new PriorityQueue(11, new NodeComparator()); children.add(exclude(currentNode, i, currentNode.parent[i])); for (int j = 0; j < n; j++) { diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java index f9015ec48d..5e45a893ba 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java @@ -2501,8 +2501,9 @@ public class BinaryMapIndexReader { } } } - for (MapObject e : resMap.keySet()) { - Street s = resMap.get(e); + for (Entry entry : resMap.entrySet()) { + MapObject e = entry.getKey(); + Street s = entry.getValue(); if (e instanceof Building && MapUtils.getDistance(e.getLocation(), lat, lon) < 40) { Building b = (Building) e; System.out.println(b.getName() + " " + s); diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java index 857eb4f4d3..cb348cf9b4 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java @@ -11,8 +11,6 @@ import java.util.Arrays; import java.util.Comparator; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import net.osmand.Collator; import net.osmand.CollatorStringMatcher; @@ -576,13 +574,12 @@ public class BinaryMapPoiReaderAdapter { } } if (!matches) { - Map lt = am.getAdditionalInfo(); - for (Entry e : lt.entrySet()) { - if(!e.getKey().contains("_name") && - !e.getKey().equals("brand")) { + for (String key : am.getAdditionalInfoKeys()) { + if(!key.contains("_name") && + !key.equals("brand")) { continue; } - matches = matcher.matches(e.getValue()); + matches = matcher.matches(am.getAdditionalInfo(key)); if (matches) { break; } @@ -812,7 +809,6 @@ public class BinaryMapPoiReaderAdapter { } private boolean checkCategories(SearchRequest req, PoiRegion region) throws IOException { - StringBuilder subType = new StringBuilder(); while (true) { int t = codedIS.readTag(); int tag = WireFormat.getTagFieldNumber(t); diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/CachedOsmandIndexes.java b/OsmAnd-java/src/main/java/net/osmand/binary/CachedOsmandIndexes.java index 4a4bec70a2..63c81d13fa 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/CachedOsmandIndexes.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/CachedOsmandIndexes.java @@ -241,9 +241,7 @@ public class CachedOsmandIndexes { cblock.type = mr.getType(); mi.cities.add(cblock); } - for(String s : index.getAdditionalTagsList()) { - mi.attributeTagsTable.add(s); - } + mi.attributeTagsTable.addAll(index.getAdditionalTagsList()); reader.addressIndexes.add(mi); reader.indexes.add(mi); } diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java b/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java index bfe638d394..bc81ca667e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java @@ -329,7 +329,7 @@ public class RouteDataObject { public String getDestinationName(String lang, boolean transliterate, boolean direction){ //Issue #3289: Treat destination:ref like a destination, not like a ref String destRef = ((getDestinationRef(direction) == null) || getDestinationRef(direction).equals(getRef(lang, transliterate, direction))) ? "" : getDestinationRef(direction); - String destRef1 = ("".equals(destRef)) ? "" : destRef + ", "; + String destRef1 = Algorithms.isEmpty(destRef) ? "" : destRef + ", "; if(names != null) { int[] kt = names.keys(); @@ -373,7 +373,7 @@ public class RouteDataObject { return destRef1 + ((transliterate) ? TransliterationHelper.transliterate(destinationDefault) : destinationDefault); } } - return "".equals(destRef) ? null : destRef; + return Algorithms.isEmpty(destRef) ? null : destRef; } public int getPoint31XTile(int i) { diff --git a/OsmAnd-java/src/main/java/net/osmand/data/Amenity.java b/OsmAnd-java/src/main/java/net/osmand/data/Amenity.java index bb1c911034..f7be034cbe 100644 --- a/OsmAnd-java/src/main/java/net/osmand/data/Amenity.java +++ b/OsmAnd-java/src/main/java/net/osmand/data/Amenity.java @@ -1,17 +1,7 @@ package net.osmand.data; -import net.osmand.Location; -import net.osmand.osm.MapPoiTypes; -import net.osmand.osm.PoiCategory; -import net.osmand.util.Algorithms; - -import org.json.JSONObject; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -21,9 +11,14 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; -import java.util.zip.GZIPInputStream; + +import org.json.JSONObject; import gnu.trove.list.array.TIntArrayList; +import net.osmand.Location; +import net.osmand.osm.MapPoiTypes; +import net.osmand.osm.PoiCategory; +import net.osmand.util.Algorithms; public class Amenity extends MapObject { @@ -101,12 +96,46 @@ public class Amenity extends MapObject { } - public Map getAdditionalInfo() { + // this method should be used carefully + public Map getInternalAdditionalInfoMap() { if (additionalInfo == null) { return Collections.emptyMap(); } return additionalInfo; } + + public Collection getAdditionalInfoValues(boolean excludeZipped) { + if (additionalInfo == null) { + return Collections.emptyList(); + } + boolean zipped = false; + for(String v : additionalInfo.values()) { + if(isContentZipped(v)) { + zipped = true; + break; + } + } + if(zipped) { + List r = new ArrayList<>(additionalInfo.size()); + for(String str : additionalInfo.values()) { + if(excludeZipped && isContentZipped(str)) { + + } else { + r.add(unzipContent(str)); + } + } + return r; + } else { + return additionalInfo.values(); + } + } + + public Collection getAdditionalInfoKeys() { + if (additionalInfo == null) { + return Collections.emptyList(); + } + return additionalInfo.keySet(); + } public void setAdditionalInfo(Map additionalInfo) { this.additionalInfo = null; @@ -187,7 +216,7 @@ public class Amenity extends MapObject { } int maxLen = 0; String lng = defLang; - for (String nm : getAdditionalInfo().keySet()) { + for (String nm : getAdditionalInfoKeys()) { if (nm.startsWith(tag + ":")) { String key = nm.substring(tag.length() + 1); String cnt = getAdditionalInfo(tag + ":" + key); @@ -209,7 +238,7 @@ public class Amenity extends MapObject { public List getNames(String tag, String defTag) { List l = new ArrayList(); - for (String nm : getAdditionalInfo().keySet()) { + for (String nm : getAdditionalInfoKeys()) { if (nm.startsWith(tag + ":")) { l.add(nm.substring(tag.length() + 1)); } else if (nm.equals(tag)) { @@ -234,7 +263,7 @@ public class Amenity extends MapObject { if (!Algorithms.isEmpty(enName)) { return enName; } - for (String nm : getAdditionalInfo().keySet()) { + for (String nm : getAdditionalInfoKeys()) { if (nm.startsWith(tag + ":")) { return getAdditionalInfo(nm); } @@ -350,4 +379,6 @@ public class Amenity extends MapObject { } return a; } + + } diff --git a/OsmAnd-java/src/main/java/net/osmand/data/MapObject.java b/OsmAnd-java/src/main/java/net/osmand/data/MapObject.java index cb121cedfc..d3700896b2 100644 --- a/OsmAnd-java/src/main/java/net/osmand/data/MapObject.java +++ b/OsmAnd-java/src/main/java/net/osmand/data/MapObject.java @@ -13,7 +13,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -351,8 +350,8 @@ public abstract class MapObject implements Comparable { return json; } - public String unzipContent(String str) { - if (str != null && str.startsWith(" gz ")) { + String unzipContent(String str) { + if (isContentZipped(str)) { try { int ind = 4; byte[] bytes = new byte[str.length() - ind]; @@ -369,6 +368,10 @@ public abstract class MapObject implements Comparable { } br.close(); str = bld.toString(); + // ugly fix of temporary problem of map generation + if(isContentZipped(str)) { + str = unzipContent(str); + } } catch (IOException e) { e.printStackTrace(); } @@ -376,6 +379,10 @@ public abstract class MapObject implements Comparable { return str; } + boolean isContentZipped(String str) { + return str != null && str.startsWith(" gz "); + } + protected static void parseJSON(JSONObject json, MapObject o) { if (json.has("name")) { o.name = json.getString("name"); diff --git a/OsmAnd-java/src/main/java/net/osmand/data/Multipolygon.java b/OsmAnd-java/src/main/java/net/osmand/data/Multipolygon.java index bf8c0a4964..6fb6db0f3c 100644 --- a/OsmAnd-java/src/main/java/net/osmand/data/Multipolygon.java +++ b/OsmAnd-java/src/main/java/net/osmand/data/Multipolygon.java @@ -61,9 +61,9 @@ public class Multipolygon { innerLinearRings.add(innerRing.toLinearRing()); } } - polygons.add(geometryFactory.createPolygon(outerRing.toLinearRing(), innerLinearRings.toArray(new LinearRing[innerLinearRings.size()]))); + polygons.add(geometryFactory.createPolygon(outerRing.toLinearRing(), innerLinearRings.toArray(new LinearRing[0]))); } - return geometryFactory.createMultiPolygon(polygons.toArray(new Polygon[polygons.size()])); + return geometryFactory.createMultiPolygon(polygons.toArray(new Polygon[0])); } public long getId() { diff --git a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java index 9885aa2fbf..d9924dc9c6 100644 --- a/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java +++ b/OsmAnd-java/src/main/java/net/osmand/map/TileSourceManager.java @@ -140,7 +140,7 @@ public class TileSourceManager { } } } - return randoms.toArray(new String[randoms.size()]); + return randoms.toArray(new String[0]); } public void setMinZoom(int minZoom) { @@ -518,8 +518,8 @@ public class TileSourceManager { } if (override || !metainfo.exists()) { BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(metainfo))); - for (String key : properties.keySet()) { - writer.write("[" + key + "]\n" + properties.get(key) + "\n"); + for (Map.Entry entry : properties.entrySet()) { + writer.write("[" + entry.getKey() + "]\n" + entry.getValue() + "\n"); } writer.close(); } diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/MapRenderingTypes.java b/OsmAnd-java/src/main/java/net/osmand/osm/MapRenderingTypes.java index d996678e44..bcbcbfc2b0 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/MapRenderingTypes.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/MapRenderingTypes.java @@ -96,8 +96,9 @@ public abstract class MapRenderingTypes { Map common = new HashMap(); String ATTACHED_KEY = "seamark:attached"; String type = ""; - for (String s : tags.keySet()) { - String value = tags.get(s); + for (Entry entry : tags.entrySet()) { + String s = entry.getKey(); + String value = entry.getValue(); if (s.equals("seamark:type")) { type = value; common.put(ATTACHED_KEY, openSeaType(value)); diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/edit/EntityParser.java b/OsmAnd-java/src/main/java/net/osmand/osm/edit/EntityParser.java index 8c3aef8163..9caa54b55c 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/edit/EntityParser.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/edit/EntityParser.java @@ -33,9 +33,10 @@ public class EntityParser { if (mo.getEnName(false).length() == 0) { mo.setEnName(tags.get(OSMTagKey.NAME_EN.getValue())); } - for (String ts : tags.keySet()) { + for (Map.Entry entry : tags.entrySet()) { + String ts = entry.getKey(); if (ts.startsWith("name:") && !ts.equals(OSMTagKey.NAME_EN.getValue())) { - mo.setName(ts.substring(("name:").length()), tags.get(ts)); + mo.setName(ts.substring(("name:").length()), entry.getValue()); } } if (mo.getName().length() == 0) { diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/io/NetworkUtils.java b/OsmAnd-java/src/main/java/net/osmand/osm/io/NetworkUtils.java index 28a1ec3fb9..7f5c008efd 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/io/NetworkUtils.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/io/NetworkUtils.java @@ -56,6 +56,55 @@ public class NetworkUtils { return e.getMessage(); } } + + public static String sendPostDataRequest(String urlText, InputStream data) { + try { + log.info("POST : " + urlText); + HttpURLConnection conn = getHttpURLConnection(urlText); + conn.setDoInput(true); + conn.setDoOutput(false); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Accept", "*/*"); + conn.setRequestProperty("User-Agent", "OsmAnd"); //$NON-NLS-1$ //$NON-NLS-2$ + conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); + OutputStream ous = conn.getOutputStream(); + ous.write(("--" + BOUNDARY + "\r\n").getBytes()); + ous.write(("content-disposition: form-data; name=\"" + "file" + "\"; filename=\"" + "image1" + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ + ous.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes()); //$NON-NLS-1$ + Algorithms.streamCopy(data, ous); + ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ + ous.flush(); + log.info("Response code and message : " + conn.getResponseCode() + " " + conn.getResponseMessage()); + if (conn.getResponseCode() != 200) { + return null; + } + StringBuilder responseBody = new StringBuilder(); + InputStream is = conn.getInputStream(); + responseBody.setLength(0); + if (is != null) { + BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); //$NON-NLS-1$ + String s; + boolean first = true; + while ((s = in.readLine()) != null) { + if (first) { + first = false; + } else { + responseBody.append("\n"); //$NON-NLS-1$ + } + responseBody.append(s); + } + is.close(); + } + Algorithms.closeStream(is); + Algorithms.closeStream(data); + Algorithms.closeStream(ous); + return responseBody.toString(); + } catch (IOException e) { + log.error(e.getMessage(), e); + return e.getMessage(); + } + } + private static final String BOUNDARY = "CowMooCowMooCowCowCow"; //$NON-NLS-1$ public static String uploadFile(String urlText, File fileToUpload, String userNamePassword, OsmOAuthAuthorizationClient client, @@ -63,8 +112,8 @@ public class NetworkUtils { URL url; try { boolean firstPrm =!urlText.contains("?"); - for (String key : additionalMapData.keySet()) { - urlText += (firstPrm ? "?" : "&") + key + "=" + URLEncoder.encode(additionalMapData.get(key), "UTF-8"); + for (Map.Entry entry : additionalMapData.entrySet()) { + urlText += (firstPrm ? "?" : "&") + entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"); firstPrm = false; } log.info("Start uploading file to " + urlText + " " +fileToUpload.getName()); diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java b/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java index f1c718465e..cf2f5a5acc 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java @@ -25,16 +25,16 @@ public class OsmOAuthAuthorizationClient { private final OsmAndJDKHttpClient httpClient; public final static Log log = PlatformUtil.getLog(OsmOAuthAuthorizationClient.class); - public OsmOAuthAuthorizationClient(String key, String secret) { + public OsmOAuthAuthorizationClient(String key, String secret, DefaultApi10a api) { httpClient = new OsmAndJDKHttpClient(JDKHttpClientConfig.defaultConfig()); service = new ServiceBuilder(key) .apiSecret(secret) .httpClient(httpClient) .callback("osmand-oauth://example.com/oauth") - .build(new OsmApi()); + .build(api); } - static class OsmApi extends DefaultApi10a { + public static class OsmApi extends DefaultApi10a { @Override public OAuth1SignatureType getSignatureType() { return OAuth1SignatureType.QUERY_STRING; @@ -56,6 +56,28 @@ public class OsmOAuthAuthorizationClient { } } + public static class OsmDevApi extends DefaultApi10a { + @Override + public OAuth1SignatureType getSignatureType() { + return OAuth1SignatureType.QUERY_STRING; + } + + @Override + public String getRequestTokenEndpoint() { + return "https://master.apis.dev.openstreetmap.org/oauth/request_token"; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://master.apis.dev.openstreetmap.org/oauth/access_token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://master.apis.dev.openstreetmap.org/oauth/authorize"; + } + } + public OsmAndJDKHttpClient getHttpClient() { return httpClient; } diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRule.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRule.java index 0ae4314dd9..b402cca664 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRule.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRule.java @@ -70,7 +70,7 @@ public class RenderingRule { i++; } } - properties = props.toArray(new RenderingRuleProperty[props.size()]); + properties = props.toArray(new RenderingRuleProperty[0]); } private int getPropertyIndex(String property){ diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRuleStorageProperties.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRuleStorageProperties.java index 3eafb803dd..4ae767561e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRuleStorageProperties.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRuleStorageProperties.java @@ -318,7 +318,7 @@ public class RenderingRuleStorageProperties { } public RenderingRuleProperty[] getPoperties() { - return rules.toArray(new RenderingRuleProperty[rules.size()]); + return rules.toArray(new RenderingRuleProperty[0]); } public List getCustomRules() { diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java index d4d97d547c..cf97dd520c 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java @@ -432,8 +432,7 @@ public class RenderingRulesStorage { for(RenderingRule ch : caseChildren) { List apply = applyRules; if(!renderingRule.getIfChildren().isEmpty()) { - apply = new ArrayList(); - apply.addAll(renderingRule.getIfChildren()); + apply = new ArrayList<>(renderingRule.getIfChildren()); if(applyRules != null) { apply.addAll(applyRules); } @@ -492,10 +491,10 @@ public class RenderingRulesStorage { } public String[] getRenderingAttributeNames() { - return renderingAttributes.keySet().toArray(new String[renderingAttributes.size()]); + return renderingAttributes.keySet().toArray(new String[0]); } public RenderingRule[] getRenderingAttributeValues() { - return renderingAttributes.values().toArray(new RenderingRule[renderingAttributes.size()]); + return renderingAttributes.values().toArray(new RenderingRule[0]); } public RenderingRule[] getRules(int state){ diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStoragePrinter.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStoragePrinter.java index 86d0c2cb73..3acdeade26 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStoragePrinter.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStoragePrinter.java @@ -152,9 +152,9 @@ public class RenderingRulesStoragePrinter { for (int i = 0; i < 15; i++) { out.println("" + indent + ti + "RenderingRule rule" + i + " = null;"); } - for (String s : storage.renderingAttributes.keySet()) { - generateRenderingRule(storage, out, indent + ti, "rule", 0, storage.renderingAttributes.get(s)); - out.println("" + indent + ti + "storage.renderingAttributes.put(" + javaString(s) + ", rule0);"); + for (Entry entry : storage.renderingAttributes.entrySet()) { + generateRenderingRule(storage, out, indent + ti, "rule", 0, entry.getValue()); + out.println("" + indent + ti + "storage.renderingAttributes.put(" + javaString(entry.getKey()) + ", rule0);"); } out.println(""+indent +"}"); } @@ -221,7 +221,7 @@ public class RenderingRulesStoragePrinter { mp+=", "; } } - if(mp.equals("")) { + if(mp.isEmpty()) { mp = "java.util.Collections.EMPTY_MAP"; } else { mp = "createMap(" +mp +")"; @@ -242,9 +242,9 @@ public class RenderingRulesStoragePrinter { private void printJavaInitConstants(RenderingRulesStorage storage, PrintStream out, String indent, String ti) { out.println("\n" + indent + "public void initConstants() {"); - for (String s : storage.renderingConstants.keySet()) { - out.println("" + indent + ti + "storage.renderingConstants.put(" + javaString(s) + ", " - + javaString(storage.renderingConstants.get(s)) + ");"); + for (Entry entry : storage.renderingConstants.entrySet()) { + out.println("" + indent + ti + "storage.renderingConstants.put(" + javaString(entry.getKey()) + ", " + + javaString(entry.getValue()) + ");"); } out.println(""+indent +"}"); } diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesTransformer.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesTransformer.java index b41a741909..cd18ad958f 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesTransformer.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesTransformer.java @@ -80,7 +80,7 @@ public class RenderingRulesTransformer { for (int i = 0; i < nl.getLength();) { Element app = (Element) nl.item(i); String pt = app.getAttribute("pattern"); - if (!pt.equals("")) { + if (!pt.isEmpty()) { if (!patterns.containsKey(pt)) { throw new IllegalStateException("Pattern '" + pt + "' is not defined"); } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java b/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java index 537e3a5f74..e6d19c1d58 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java @@ -754,21 +754,21 @@ public class GeneralRouter implements VehicleRouter { } public RouteAttributeEvalRule[] getRules() { - return rules.toArray(new RouteAttributeEvalRule[rules.size()]); + return rules.toArray(new RouteAttributeEvalRule[0]); } public String[] getParamKeys() { if(paramContext == null) { return new String[0]; } - return paramContext.vars.keySet().toArray(new String[paramContext.vars.size()]); + return paramContext.vars.keySet().toArray(new String[0]); } public String[] getParamValues() { if(paramContext == null) { return new String[0]; } - return paramContext.vars.values().toArray(new String[paramContext.vars.size()]); + return paramContext.vars.values().toArray(new String[0]); } private Object evaluate(RouteDataObject ro) { @@ -988,19 +988,19 @@ public class GeneralRouter implements VehicleRouter { public RouteAttributeExpression[] getExpressions() { - return expressions.toArray(new RouteAttributeExpression[expressions.size()]); + return expressions.toArray(new RouteAttributeExpression[0]); } public String[] getParameters() { - return parameters.toArray(new String[parameters.size()]); + return parameters.toArray(new String[0]); } public String[] getTagValueCondDefTag() { - return tagValueCondDefTag.toArray(new String[tagValueCondDefTag.size()]); + return tagValueCondDefTag.toArray(new String[0]); } public String[] getTagValueCondDefValue() { - return tagValueCondDefValue.toArray(new String[tagValueCondDefValue.size()]); + return tagValueCondDefValue.toArray(new String[0]); } public boolean[] getTagValueCondDefNot() { diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java index 17eb567813..74dceb13a1 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java @@ -918,7 +918,7 @@ public class RoutePlannerFrontEnd { private List runNativeRouting(final RoutingContext ctx, RouteSegment recalculationEnd) throws IOException { refreshProgressDistance(ctx); - RouteRegion[] regions = ctx.reverseMap.keySet().toArray(new BinaryMapRouteReaderAdapter.RouteRegion[ctx.reverseMap.size()]); + RouteRegion[] regions = ctx.reverseMap.keySet().toArray(new RouteRegion[0]); ctx.checkOldRoutingFiles(ctx.startX, ctx.startY); ctx.checkOldRoutingFiles(ctx.targetX, ctx.targetY); diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java index d7ebbaba8f..4df69c3adc 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java @@ -1717,7 +1717,7 @@ public class RouteResultPreparation { } } } - Integer[] array = possibleTurns.toArray(new Integer[possibleTurns.size()]); + Integer[] array = possibleTurns.toArray(new Integer[0]); Arrays.sort(array, new Comparator() { @Override diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java index 3bfbaec0da..584be83bb3 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java @@ -802,7 +802,7 @@ public class RoutingContext { } public BinaryMapIndexReader[] getMaps() { - return map.keySet().toArray(new BinaryMapIndexReader[map.size()]); + return map.keySet().toArray(new BinaryMapIndexReader[0]); } public int getVisitedSegments() { diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TransportStopsRouteReader.java b/OsmAnd-java/src/main/java/net/osmand/router/TransportStopsRouteReader.java index 7428196332..13da3748bb 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/TransportStopsRouteReader.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/TransportStopsRouteReader.java @@ -325,9 +325,7 @@ public class TransportStopsRouteReader { // merge first part if (commonStopFirst < commonStopSecond || (commonStopFirst == commonStopSecond && firstSegment.get(0).isMissingStop())) { - for (int i = 0; i <= commonStopFirst; i++) { - firstSegment.remove(0); - } + firstSegment.subList(0, commonStopFirst + 1).clear(); for (int i = commonStopSecond; i >= 0; i--) { firstSegment.add(0, segmentToMerge.get(i)); } diff --git a/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java b/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java index becacd2775..e63870b1a7 100644 --- a/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java +++ b/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java @@ -741,7 +741,7 @@ public class SearchUICore { } } if (Algorithms.isEmpty(object.alternateName) && object.object instanceof Amenity) { - for (String value : ((Amenity) object.object).getAdditionalInfo().values()) { + for (String value : ((Amenity) object.object).getAdditionalInfoValues(true)) { if (phrase.getFirstUnknownNameStringMatcher().matches(value)) { object.alternateName = value; break; diff --git a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java index e5c791a780..c221d2ca77 100644 --- a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java +++ b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java @@ -602,7 +602,7 @@ public class SearchCoreFactory { sr.localeName = object.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate()); if (!nm.matches(sr.localeName) && !nm.matches(sr.otherNames) - && !nm.matches(object.getAdditionalInfo().values())) { + && !nm.matches(object.getAdditionalInfoValues(false))) { return false; } sr.object = object; @@ -1059,7 +1059,7 @@ public class SearchCoreFactory { if (!poiAdditionals.isEmpty()) { boolean found = false; for (String add : poiAdditionals) { - if(object.getAdditionalInfo().containsKey(add)) { + if (object.getAdditionalInfoKeys().contains(add)) { found = true; break; } diff --git a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java index 2a3fc59521..09dcdc372b 100644 --- a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java +++ b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java @@ -720,7 +720,7 @@ public class SearchPhrase { if (result.containsKey(currRegionName)) { result.get(currRegionName).add(r); } else { - result.put(currRegionName, new ArrayList<>(Arrays.asList(r))); + result.put(currRegionName, new ArrayList<>(Collections.singletonList(r))); } it.remove(); } diff --git a/OsmAnd-java/src/main/java/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/main/java/net/osmand/util/GeoPointParserUtil.java index 1383f4ae4a..951ae870e2 100644 --- a/OsmAnd-java/src/main/java/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/main/java/net/osmand/util/GeoPointParserUtil.java @@ -62,7 +62,7 @@ public class GeoPointParserUtil { private static Map getQueryParameters(String query) { final LinkedHashMap map = new LinkedHashMap(); - if (query != null && !query.equals("")) { + if (query != null && !query.isEmpty()) { String[] params = query.split("[&/]"); for (String p : params) { String[] keyValue = p.split("="); @@ -803,10 +803,10 @@ public class GeoPointParserUtil { if (map.size() > 0) uriString += "?"; int i = 0; - for (String key : map.keySet()) { + for (Map.Entry entry : map.entrySet()) { if (i > 0) uriString += "&"; - uriString += key + "=" + map.get(key); + uriString += entry.getKey() + "=" + entry.getValue(); i++; } return uriString; diff --git a/OsmAnd-java/src/main/java/net/osmand/util/OpeningHoursParser.java b/OsmAnd-java/src/main/java/net/osmand/util/OpeningHoursParser.java index 01fee5cd9e..f87a1d4d4e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/util/OpeningHoursParser.java +++ b/OsmAnd-java/src/main/java/net/osmand/util/OpeningHoursParser.java @@ -6,6 +6,7 @@ import java.text.DateFormatSymbols; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -1812,7 +1813,7 @@ public class OpeningHoursParser { TokenType currentParse = TokenType.TOKEN_UNKNOWN; TokenType currentParseParent = TokenType.TOKEN_UNKNOWN; List listOfPairs = new ArrayList<>(); - Set presentTokens = new HashSet<>(); + Set presentTokens = EnumSet.noneOf(TokenType.class); Token[] currentPair = new Token[2]; listOfPairs.add(currentPair); Token prevToken = null; diff --git a/OsmAnd-telegram/res/values-es/strings.xml b/OsmAnd-telegram/res/values-es/strings.xml index 29442e4212..d253eabfff 100644 --- a/OsmAnd-telegram/res/values-es/strings.xml +++ b/OsmAnd-telegram/res/values-es/strings.xml @@ -250,7 +250,7 @@ Elige la hora de visualización Fecha de Inicio — Fin Mensajes guardados - Seleccione la zona horaria que desea mostrar en los mensajes de ubicación. + Seleccione la zona horaria a mostrar en sus mensajes de ubicación. Zona horaria Unidades y formatos Cambia las unidades de longitud. diff --git a/OsmAnd-telegram/res/values-is/strings.xml b/OsmAnd-telegram/res/values-is/strings.xml index 6fa1ae4614..a915a2e4f4 100644 --- a/OsmAnd-telegram/res/values-is/strings.xml +++ b/OsmAnd-telegram/res/values-is/strings.xml @@ -43,8 +43,8 @@ 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 + Staða OsmAnd-rakningar + OsmAnd-rakning Hópur mín/ml Netþjónn @@ -211,12 +211,12 @@ Ekki fundist ennþá Móttók GPX-punkta: %1$s Deili staðsetningu - Hvernig á að slökkva á OsmAnd-rekjaranum úr Telegram + Hvernig á að slökkva á OsmAnd-rakningu úr Telegram Ekki sent ennþá OsmAnd nettengdur GPS-rekjari - Skrá út úr OsmAnd-rekjara\? + Skrá út úr OsmAnd-rakningu\? Kveikt er á deilingu (slökkva) - Hvernig á að slökkva á OsmAnd-rekjaranum úr Telegram + Hvernig á að slökkva á OsmAnd-rakningu úr Telegram Virkjaðu \"Staðsetning\" í stillingunum stýrikerfisins Tengiliðir og hópar sem deila staðsetningu til þín. Tengstu við internetið til að geta skráð þig til fulls út úr Telegram. @@ -234,10 +234,10 @@ Veldu hvaða útgáfu OsmAnd þú vilt nota Gera alla deilingu óvirka Uppfærðu OsmAnd til að skoða gögn á kortinu - Veldu tímabelti til birtingar í staðsetningarskilaboðum þínum + Veldu tímabelti til birtingar í staðsetningarskilaboðum þínum. Veldu eina af staðsetningarþjónustunum til að deila staðsetningu þinni. Stilla tímabil þar sem allir eru sýnilegir - Veldu þá útgáfu OsmAnd sem OsmAnd-rekjarinn notar til að birta staðsetningar. + Veldu þá útgáfu OsmAnd sem OsmAnd-rakningin notar til að birta staðsetningar. Endilega settu upp Telegram og skráðu notandaaðgang. Settu inn Telegram-símanúmerið þitt á alþjóðlegu sniði Virkja vöktun til að vista allar staðsetningar í aðgerðaferli. @@ -260,4 +260,15 @@ Síðasta uppfærða staðsetning: Veldu nafn sem þú hefur ekki þegar notað Ekki mögulegt að senda á Telegram-spjöll: + Til að afturkalla heimildir til deilingar á staðsetningu, opnaðu Telegram, farðu í Stillingar → Gagnaleynd og öryggi → Setur, og bittu enda á setu OsmAnd-rakningar. + Þú getur útbúið og skoðað auðkenningu tækis (device ID) í Telegram-biðlaraforritinu með því að nota %1$s spjallvélmennið. %2$s + Ertu viss að þú viljir skrá þig út úr OsmAnd-rakningu þannig að þú getir ekki lengur deilt þinni staðsetningu eða séð staðsetningu annarra\? + Slokktu á bestun rafhlöðunýtingar fyrir OsmAnd-rakningu svo ekki slökkni á henni þegar forritið fer í bakgrunnsham (t.d. slökkt er á skjá). + OsmAnd-rakning er eitt af biðlaraforritunum sem nota opna Telegram-kerfið. Tengiliðirnir þínir geta notað eitthvað annað Telegram-biðlaraforrit. + OsmAnd-rakning gerir þér kleift að deila staðsetningu þinni og að sjá aðra í OsmAnd.

Forritið notar Telegram API-forritsviðmótið, þannig að þú verður að vera með Telegram-aðgang.
+ Ef þú ætlar að tengja mörg tæki við einn Telegram-notandaaðgang, þarftu að nota annað tæki til að deila staðsetningunni þinni. + Rauntíma + Breyta bestunarstillingum rafhlöðu til að auka stöðugleika í deilingu staðsetningar. + Veldu tímann sem valdir tengiliðir og hópar munu sjá staðsetningu þína í rauntíma. + Rauntíma núna \ No newline at end of file diff --git a/OsmAnd-telegram/res/values-it/strings.xml b/OsmAnd-telegram/res/values-it/strings.xml index 05cf56a8da..6d1e62edc7 100644 --- a/OsmAnd-telegram/res/values-it/strings.xml +++ b/OsmAnd-telegram/res/values-it/strings.xml @@ -267,4 +267,6 @@ ERR Controlla e condividi i log dettagliati dell\'applicazione Logcat buffer + Invia rapporto + Esporta \ No newline at end of file diff --git a/OsmAnd-telegram/res/values-sr/strings.xml b/OsmAnd-telegram/res/values-sr/strings.xml index 52c261dbe5..4220079b9b 100644 --- a/OsmAnd-telegram/res/values-sr/strings.xml +++ b/OsmAnd-telegram/res/values-sr/strings.xml @@ -267,4 +267,8 @@ Последњи одговор: %1$ Последње ажурирање из Телеграма: %1$ Грешка + Извези + Logcat бафер + Проверите и поделите детаљне записе апликације + Пошаљи извештај \ No newline at end of file diff --git a/OsmAnd/AndroidManifest-library.xml b/OsmAnd/AndroidManifest-library.xml new file mode 100644 index 0000000000..379f1ce963 --- /dev/null +++ b/OsmAnd/AndroidManifest-library.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index c52dac72ad..f356b2d575 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -40,15 +40,6 @@ android { keyAlias "osmand" keyPassword System.getenv("OSMAND_APK_PASSWORD") } - - publishingHuawei { - storeFile file("/var/lib/jenkins/osmand_hw_key") - storePassword System.getenv("OSMAND_HW_APK_PASSWORD") - keyAlias "osmand" - keyPassword System.getenv("OSMAND_HW_APK_PASSWORD") - v1SigningEnabled true - v2SigningEnabled true - } } defaultConfig { @@ -206,20 +197,10 @@ android { buildTypes { debug { - buildConfigField "String", "OPR_BASE_URL", "\"https://test.openplacereviews.org/\"" - buildConfigField "String", "OSM_OAUTH_CONSUMER_KEY", "\"Ti2qq3fo4i4Wmuox3SiWRIGq3obZisBHnxmcM05y\"" - buildConfigField "String", "OSM_OAUTH_CONSUMER_SECRET", "\"lxulb3HYoMmd2cC4xxNe1dyfRMAY8dS0eNihJ0DM\"" signingConfig signingConfigs.development } release { - buildConfigField "String", "OPR_BASE_URL", "\"https://test.openplacereviews.org/\"" - buildConfigField "String", "OSM_OAUTH_CONSUMER_KEY", "\"Ti2qq3fo4i4Wmuox3SiWRIGq3obZisBHnxmcM05y\"" - buildConfigField "String", "OSM_OAUTH_CONSUMER_SECRET", "\"lxulb3HYoMmd2cC4xxNe1dyfRMAY8dS0eNihJ0DM\"" - if (gradle.startParameter.taskNames.toString().contains("huawei")) { - signingConfig signingConfigs.publishingHuawei - } else { - signingConfig signingConfigs.publishing - } + signingConfig signingConfigs.publishing } } @@ -526,4 +507,6 @@ dependencies { implementation 'com.jaredrummler:colorpicker:1.1.0' freehuaweiImplementation 'com.huawei.hms:iap:5.0.2.300' + + implementation "org.bouncycastle:bcpkix-jdk15on:1.56" } diff --git a/OsmAnd/build.gradle.lib b/OsmAnd/build.gradle.lib new file mode 100644 index 0000000000..fa1d94d3ce --- /dev/null +++ b/OsmAnd/build.gradle.lib @@ -0,0 +1,424 @@ +apply plugin: 'com.android.library' + +task printc { + configurations.each { if(it.isCanBeResolved()) println it.name } +} + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + // compileNdkVersion "android-ndk-r17b" + + defaultConfig { + minSdkVersion 15 + targetSdkVersion 29 + multiDexEnabled true + vectorDrawables.useSupportLibrary = true + } + + lintOptions { + tasks.lint.enabled = false + abortOnError false + } + + aaptOptions { + // Don't compress any embedded resources + noCompress "qz" + cruncherEnabled = false + } + + dexOptions { + javaMaxHeapSize "4g" + } + + sourceSets { + main { + manifest.srcFile "AndroidManifest-library.xml" + jni.srcDirs = [] + jniLibs.srcDirs = ["libs"] + aidl.srcDirs = ["src"] + java.srcDirs = ["src", "src-google"] + resources.srcDirs = ["src"] + renderscript.srcDirs = ["src"] + res.srcDirs = ["res"] + assets.srcDirs = ["assets"] + } + debug { + } + + legacy { + jniLibs.srcDirs = ["libc++"] + } + } + + flavorDimensions "coreversion", "abi" + productFlavors { + // ABI + armv7 { + dimension "abi" + ndk { + abiFilter 'armeabi-v7a' + } + } + arm64 { + dimension "abi" + ndk { + abiFilter 'arm64-v8a' + } + } + x86 { + dimension "abi" + ndk { + abiFilters 'x86', 'x86_64' + } + } + armonly { + dimension "abi" + ndk { + abiFilters 'arm64-v8a', 'armeabi-v7a' + } + } + fat { + dimension "abi" + ndk { + abiFilters 'arm64-v8a', 'x86', 'x86_64', 'armeabi-v7a' + } + } + + // CoreVersion + // Build that doesn't include 3D OpenGL + legacy { + dimension "coreversion" + } + } + + buildTypes { + debug { + debuggable true + } + + release { + debuggable false + } + } +} + +def replaceNoTranslate(line) { + if (line.contains("\"versionFeatures\"")) { + return line.replaceAll(">[^<]*<", ">" + "" + "<") + } + return line; +} + +task updateNoTranslate(type: Copy) { + from('.') { + include 'no_translate.xml' + filter { + line -> replaceNoTranslate(line); + } + } + into 'res/values/' +} + +task validateTranslate { + println "Validating translations" + + file("res").eachFileRecurse groovy.io.FileType.FILES, { + if (it.name == "strings.xml" || it.name == "phrases.xml") { + it.eachLine { line -> + if (line.contains("\$ s") || line.contains("\$ d") || line.contains("\$ f") || + line.contains(" \$s") || line.contains(" \$d") || line.contains(" \$f") || + line.contains("1\$ ") || line.contains("2\$ ") || line.contains("3\$ ") || + line.contains("%1s") || line.contains(" 1\$s") || + (line.contains("% \$") || line.contains("% 1") || line.contains("% 2") || + line.contains("% 3") || line.contains("% s"))) { + throw new GradleException("Incorrect translation " + it.getAbsolutePath() + " " + line); + } + } + } + } +} + +task downloadWorldMiniBasemap { + doLast { + ant.get(src: 'http://builder.osmand.net/basemap/World_basemap_mini_2.obf', dest: 'assets/World_basemap_mini.obf', skipexisting: 'true') + } +} + +task collectVoiceAssets(type: Sync) { + from "../../resources/voice" + into "assets/voice" + include "**/*.js" +} + +task cleanNoTranslate(type: Delete) { + delete('res/values/no_translate.xml') +} + +task collectFonts(type: Copy) { + from "../../resources/fonts" + from "../../resources/rendering_styles/fonts" +// from "../../resources/rendering_styles/fonts/OpenSans" + into "assets/fonts" + include "*.ttf" +} + +task collectHelpContentsStyle(type: Copy) { + from("../../help/website/help/") { + include "style.css" + } + into "assets" +} + +task collectHelpContentsAssets(type: Copy) { + from("../../help/website/help") { + include "about.html" + include "changes.html" + include "faq.html" + include "technical-articles.html" + include "map-legend.html" + } + from("../../help/website/feature_articles") { + include "*.html" + } + from("../../help/website/blog_articles") { + include "osmand-3-8-released.html" + } + into "assets/feature_articles" +} + +task copyPoiCategories(type: Copy) { + from("../../resources/poi") { + include "poi_categories.json" + } + into "assets" +} + +task copyMapShaderIcons(type: Sync) { + // from "../../resources/rendering_styles/style-icons/map-shaders-png" + // into "res/" + from "../../resources/rendering_styles/style-icons/map-shaders-vector" + into "res/drawable" + include "**/*.png", "**/*.xml" + preserve { + include '**/*' + exclude "**/h_*" + } +} + +task copyMapPOIIcons(type: Sync) { + from "../../resources/rendering_styles/style-icons/map-icons-vector" + into "res/drawable/" + // from "../../resources/rendering_styles/style-icons/map-icons-png" + // into "res/" + + include "**/*.png", "**/*.xml" + preserve { + include '**/*' + exclude "**/mm_*" + } +} + +task copyLargePOIIcons(type: Sync) { + from "../../resources/rendering_styles/style-icons/poi-icons-vector" + into "res/drawable/" + include "**/*.png", "**/*.xml" + preserve { + include '**/*' + exclude "**/mx_*" + } +} + +task copyWidgetIconsXhdpi(type: Sync) { + from "res/drawable-xxhdpi/" + into "res/drawable-large-xhdpi/" + include "**/widget_*.png", "**/widget_*.xml", "**/map_*.xml", "**/map_*.png" + preserve { + include '*' + exclude "**/widget_*.png", "**/widget_*.xml", "**/map_*.xml", "**/map_*.png" + } +} + +task copyWidgetIconsHdpi(type: Sync) { + from "res/drawable-xhdpi/" + into "res/drawable-large-hdpi/" + include "**/widget_*.png", "**/widget_*.xml", "**/map_*.xml", "**/map_*.png" + preserve { + include '*' + exclude "**/widget_*.png", "**/widget_*.xml", "**/map_*.xml", "**/map_*.png" + } +} + +task copyWidgetIcons(type: Sync) { + from "res/drawable-hdpi/" + into "res/drawable-large/" + include "**/widget_*.png", "**/widget_*.xml", "**/map_*.xml", "**/map_*.png" + preserve { + include '*' + exclude "**/widget_*.png", "**/widget_*.xml", "**/map_*.xml", "**/map_*.png" + } +} + +task collectExternalResources { + dependsOn collectVoiceAssets, + collectFonts, + collectHelpContentsAssets, + collectHelpContentsStyle, + copyMapShaderIcons, + copyMapPOIIcons, + copyLargePOIIcons, + updateNoTranslate, + validateTranslate, + copyWidgetIcons, + copyWidgetIconsHdpi, + copyWidgetIconsXhdpi, + copyPoiCategories, + downloadWorldMiniBasemap +} + +// Legacy core build +import org.apache.tools.ant.taskdefs.condition.Os + +import java.util.regex.Pattern + +task buildOsmAndCore(type: Exec) { + Gradle gradle = getGradle() + String tskReqStr = gradle.getStartParameter().getTaskRequests().toString().toLowerCase() + String flavour = ""; + if(!tskReqStr.contains("fat")) { + if(tskReqStr.contains("arm64")) { + flavour = flavour.length() == 0 ? "ARM64_ONLY" : "" + } + if(tskReqStr.contains("armv7")) { + flavour = flavour.length() == 0 ? "ARMV7_ONLY" : "" + } + if(tskReqStr.contains("armonly")) { + flavour = flavour.length() == 0 ? "ARM_ONLY" : "" + } + if(tskReqStr.contains("x86")) { + flavour = flavour.length() == 0 ? "X86_ONLY" : "" + } + } + + description "Build Legacy OsmAndCore" + + if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + if(flavour.length() > 0) { + environment "$flavour", "1" + } + commandLine "bash", file("./old-ndk-build.sh").getAbsolutePath() + } else { + commandLine "cmd", "/c", "echo", "Not supported" + } +} + +task cleanupDuplicatesInCore() { + dependsOn buildOsmAndCore + // doesn't work for legacy debug builds + doLast { + file("libc++/armeabi-v7a").mkdirs() + file("libs/armeabi-v7a/libc++_shared.so").renameTo(file("libc++/armeabi-v7a/libc++_shared.so")) + file("libc++/arm64-v8a").mkdirs() + file("libs/arm64-v8a/libc++_shared.so").renameTo(file("libc++/arm64-v8a/libc++_shared.so")) + file("libc++/x86").mkdirs() + file("libs/x86/libc++_shared.so").renameTo(file("libc++/x86/libc++_shared.so")) + file("libc++/x86_64").mkdirs() + file("libs/x86_64/libc++_shared.so").renameTo(file("libc++/x86_64/libc++_shared.so")) + } +} + +afterEvaluate { + android.libraryVariants.all { variant -> + variant.javaCompiler.dependsOn(collectExternalResources, buildOsmAndCore, cleanupDuplicatesInCore) + } +} + +task appStart(type: Exec) { + // linux + commandLine 'adb', 'shell', 'am', 'start', '-n', 'net.osmand.plus/net.osmand.plus.activities.MapActivity' + // windows + // commandLine 'cmd', '/c', 'adb', 'shell', 'am', 'start', '-n', 'net.osmand.plus/net.osmand.plus.activities.MapActivity' +} + +artifacts { + archives(file("../OsmAnd-java/build/libs/OsmAnd-java-android-1.0.jar")) { + name "OsmAnd-java-android" + type "jar" + } +} + +// Uploading artifacts to local path +group = 'net.osmand' +uploadArchives { + repositories.ivy { + // credentials { + // username "" + // password "" + // } + + url = System.getenv("OSMAND_BINARIES_IVY_ROOT") ?: "./" + layout "pattern" , { + artifact "[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" + } + +// def gitInfo = "git describe --long".execute().text.trim() +// def parsedGitInfo = Pattern.compile("v(\\d+\\.\\d+)-([\\d.]+)-(\\w+)").matcher(gitInfo) +// assert parsedGitInfo.matches() +// version = parsedGitInfo.group(1) + "-SNAPSHOT" + version = "1.0-SNAPSHOT" + } +} + +dependencies { + implementation project(path: ':OsmAnd-java', configuration: 'android') + implementation project(':OsmAnd-api') + implementation 'androidx.multidex:multidex:2.0.1' + implementation 'androidx.gridlayout:gridlayout:1.0.0' + implementation 'androidx.cardview:cardview:1.0.0' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.browser:browser:1.0.0' + implementation 'androidx.preference:preference:1.1.0' + implementation fileTree(include: ['gnu-trove-osmand.jar', 'icu4j-49_1_patched.jar'], dir: 'libs') + + implementation group: 'commons-logging', name: 'commons-logging', version: '1.2' + implementation 'commons-codec:commons-codec:1.11' + implementation 'it.unibo.alice.tuprolog:tuprolog:3.2.1' + implementation 'org.apache.commons:commons-compress:1.17' + implementation 'com.moparisthebest:junidecode:0.1.1' + implementation 'org.immutables:gson:2.5.0' + implementation 'com.vividsolutions:jts-core:1.14.0' + implementation 'com.google.openlocationcode:openlocationcode:1.0.4' + implementation 'com.android.billingclient:billing:2.0.3' + // turn off for now + //implementation 'com.atilika.kuromoji:kuromoji-ipadic:0.9.0' + implementation 'com.squareup.picasso:picasso:2.71828' + implementation 'me.zhanghai.android.materialprogressbar:library:1.4.2' + // JS core + implementation group: 'org.mozilla', name: 'rhino', version: '1.7.9' +// size restrictions +// implementation 'com.ibm.icu:icu4j:50.1' +// implementation 'net.sf.trove4j:trove4j:3.0.3' + +// qtcoreImplementation fileTree(include: ['QtAndroid.jar', 'QtAndroidBearer.jar'], dir: 'libs') +// qtcoredebugImplementation fileTree(include: ['QtAndroid.jar', 'QtAndroidBearer.jar'], dir: 'libs') + + legacyImplementation "net.osmand:OsmAndCore_android:0.1-SNAPSHOT@jar" +// qtcoredebugImplementation "net.osmand:OsmAndCore_androidNativeDebug:0.1-SNAPSHOT@aar" +// qtcoredebugImplementation "net.osmand:OsmAndCore_android:0.1-SNAPSHOT@aar" +// qtcoreImplementation "net.osmand:OsmAndCore_androidNativeRelease:0.1-SNAPSHOT@aar" +// qtcoreImplementation "net.osmand:OsmAndCore_android:0.1-SNAPSHOT@aar" + implementation ("com.getkeepsafe.taptargetview:taptargetview:1.12.0"){ + exclude group: 'com.android.support' + } + implementation 'com.github.PhilJay:MPAndroidChart:v3.0.1' + implementation ("com.github.HITGIF:TextFieldBoxes:1.4.5"){ + exclude group: 'com.android.support' + } + implementation('com.github.scribejava:scribejava-apis:7.1.1'){ + exclude group: "com.fasterxml.jackson.core" + } + implementation 'com.jaredrummler:colorpicker:1.1.0' + + implementation 'org.bouncycastle:bcpkix-jdk15on:1.56' +} diff --git a/OsmAnd/no_translate.xml b/OsmAnd/no_translate.xml index 719b6ee8fe..20d7a424ca 100644 --- a/OsmAnd/no_translate.xml +++ b/OsmAnd/no_translate.xml @@ -41,4 +41,9 @@ items modified OsmAnd Unlimited Markers + https://test.openplacereviews.org/ + v8G8r9NLJZGMV4he5lwbQlz620FNVARKjI9Bm5UJ + jDvM95Ne1Bq2BDTmIfB6b3ZMxvdK87WGfp6DC07J + Ti2qq3fo4i4Wmuox3SiWRIGq3obZisBHnxmcM05y + lxulb3HYoMmd2cC4xxNe1dyfRMAY8dS0eNihJ0DM diff --git a/OsmAnd/res/animator/appbar_always_elevated.xml b/OsmAnd/res/animator/appbar_always_elevated.xml new file mode 100644 index 0000000000..c8378c1c29 --- /dev/null +++ b/OsmAnd/res/animator/appbar_always_elevated.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/ic_action_plan_route_point_colored.xml b/OsmAnd/res/drawable/ic_action_plan_route_point_colored.xml new file mode 100644 index 0000000000..7fb6be0078 --- /dev/null +++ b/OsmAnd/res/drawable/ic_action_plan_route_point_colored.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/OsmAnd/res/layout/account_details.xml b/OsmAnd/res/layout/account_details.xml new file mode 100644 index 0000000000..9e6e4497d7 --- /dev/null +++ b/OsmAnd/res/layout/account_details.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/activity_opr_webview.xml b/OsmAnd/res/layout/activity_opr_webview.xml index 9d3f28c67a..9e32d56df4 100644 --- a/OsmAnd/res/layout/activity_opr_webview.xml +++ b/OsmAnd/res/layout/activity_opr_webview.xml @@ -1,25 +1,23 @@ + android:layout_height="@dimen/toolbar_height"> diff --git a/OsmAnd/res/layout/bottom_sheet_item_with_descr_and_checkbox_56dp.xml b/OsmAnd/res/layout/bottom_sheet_item_with_descr_and_checkbox_56dp.xml index 34e329d8a3..65fc03610c 100644 --- a/OsmAnd/res/layout/bottom_sheet_item_with_descr_and_checkbox_56dp.xml +++ b/OsmAnd/res/layout/bottom_sheet_item_with_descr_and_checkbox_56dp.xml @@ -33,7 +33,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" - android:maxLines="1" + android:maxLines="2" android:textAppearance="@style/TextAppearance.ListItemTitle" tools:text="Some title"/> diff --git a/OsmAnd/res/layout/custom_radio_buttons.xml b/OsmAnd/res/layout/custom_radio_buttons.xml index a5ec943f6a..d768e58004 100644 --- a/OsmAnd/res/layout/custom_radio_buttons.xml +++ b/OsmAnd/res/layout/custom_radio_buttons.xml @@ -4,7 +4,8 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/custom_radio_buttons" android:layout_width="match_parent" - android:layout_height="@dimen/dialog_button_height" + android:minHeight="@dimen/dialog_button_height" + android:layout_height="wrap_content" android:layout_marginStart="@dimen/content_padding" android:layout_marginEnd="@dimen/content_padding" android:background="?attr/btn_bg_border_inactive" diff --git a/OsmAnd/res/layout/dialog_button_with_icon.xml b/OsmAnd/res/layout/dialog_button_with_icon.xml new file mode 100644 index 0000000000..264f884495 --- /dev/null +++ b/OsmAnd/res/layout/dialog_button_with_icon.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/enough_space_warning_card.xml b/OsmAnd/res/layout/enough_space_warning_card.xml index a39076eb99..d572d20366 100644 --- a/OsmAnd/res/layout/enough_space_warning_card.xml +++ b/OsmAnd/res/layout/enough_space_warning_card.xml @@ -36,6 +36,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:letterSpacing="@dimen/text_button_letter_spacing" + android:paddingBottom="@dimen/measurement_tool_menu_title_padding_bottom" android:text="@string/export_not_enough_space" android:textColor="?android:textColorPrimary" android:textSize="@dimen/default_list_text_size" diff --git a/OsmAnd/res/layout/follow_track_options.xml b/OsmAnd/res/layout/follow_track_options.xml index 0877fcc307..4523599e6c 100644 --- a/OsmAnd/res/layout/follow_track_options.xml +++ b/OsmAnd/res/layout/follow_track_options.xml @@ -75,7 +75,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="?attr/route_info_bg" - android:foreground="@drawable/bg_contextmenu_shadow" android:foregroundGravity="top|fill_horizontal"> + + + android:background="@android:color/transparent" + android:stateListAnimator="@animator/appbar_always_elevated"> - + + app:srcCompat="@drawable/ic_arrow_back" + app:tint="@color/icon_color_default_light" /> - - - + android:layout_height="match_parent" + android:layout_below="@id/toolbar" + android:layout_above="@id/buttons"> + - + + + + + + + + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/content_padding" + android:layout_marginTop="@dimen/content_padding_small" + android:layout_marginRight="@dimen/content_padding" + android:layout_marginBottom="@dimen/content_padding_small" + android:layout_alignParentBottom="true" + android:orientation="vertical"> - + android:layout_height="@dimen/dialog_button_height" + android:layout_marginBottom="@dimen/content_padding_small" /> - + android:layout_height="@dimen/dialog_button_height" /> - \ No newline at end of file + \ No newline at end of file diff --git a/OsmAnd/res/layout/open_osm_note_text.xml b/OsmAnd/res/layout/open_osm_note_text.xml new file mode 100644 index 0000000000..c3bb2dccd8 --- /dev/null +++ b/OsmAnd/res/layout/open_osm_note_text.xml @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/opr_add_photo.xml b/OsmAnd/res/layout/opr_add_photo.xml new file mode 100644 index 0000000000..80d43411fe --- /dev/null +++ b/OsmAnd/res/layout/opr_add_photo.xml @@ -0,0 +1,41 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/osm_login_data.xml b/OsmAnd/res/layout/osm_login_data.xml index 4679608265..363287fe72 100644 --- a/OsmAnd/res/layout/osm_login_data.xml +++ b/OsmAnd/res/layout/osm_login_data.xml @@ -1,5 +1,6 @@ + android:hint="@string/user_login" + app:boxBackgroundColor="?attr/text_input_background" + app:boxStrokeColor="@color/osmand_orange" + app:hintTextColor="@color/text_color_secondary_light"> + android:hint="@string/user_password" + app:boxBackgroundColor="?attr/text_input_background" + app:boxStrokeColor="@color/osmand_orange" + app:hintTextColor="@color/text_color_secondary_light"> diff --git a/OsmAnd/res/layout/send_gpx_fragment.xml b/OsmAnd/res/layout/send_gpx_fragment.xml index f079141e17..795b169300 100644 --- a/OsmAnd/res/layout/send_gpx_fragment.xml +++ b/OsmAnd/res/layout/send_gpx_fragment.xml @@ -33,13 +33,13 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/bottom_sheet_content_margin" android:hint="@string/shared_string_description" + app:boxBackgroundColor="?attr/text_input_background" app:boxStrokeColor="@color/osmand_orange" app:hintTextColor="@color/text_color_secondary_light"> @@ -51,6 +51,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/bottom_sheet_content_margin" android:hint="@string/gpx_tags_txt" + app:boxBackgroundColor="?attr/text_input_background" app:boxStrokeColor="@color/osmand_orange" app:helperText="@string/enter_text_separated" app:helperTextEnabled="true" @@ -62,7 +63,6 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/subHeaderPadding" android:imeOptions="actionDone" - android:background = "?attr/text_input_background" android:text="osmand" /> @@ -141,66 +141,13 @@ - + + - - - - - - - - - - - - + android:layout_height="@dimen/content_padding_small" /> \ No newline at end of file diff --git a/OsmAnd/res/layout/send_osm_note_fragment.xml b/OsmAnd/res/layout/send_osm_note_fragment.xml index 6cc897ee89..12205d77bb 100644 --- a/OsmAnd/res/layout/send_osm_note_fragment.xml +++ b/OsmAnd/res/layout/send_osm_note_fragment.xml @@ -1,169 +1,117 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:osmand="http://schemas.android.com/apk/res-auto" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + + diff --git a/OsmAnd/res/layout/send_poi_fragment.xml b/OsmAnd/res/layout/send_poi_fragment.xml index 2f1ee7cf51..751c0b1fe8 100644 --- a/OsmAnd/res/layout/send_poi_fragment.xml +++ b/OsmAnd/res/layout/send_poi_fragment.xml @@ -1,123 +1,77 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:osmand="http://schemas.android.com/apk/res-auto" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> - + - + - + + android:imeOptions="actionDone" + android:lineSpacingExtra="5sp"/> - + - + - + - + - + - - - - - - - - - diff --git a/OsmAnd/res/layout/settings_group_title.xml b/OsmAnd/res/layout/settings_group_title.xml new file mode 100644 index 0000000000..269d018021 --- /dev/null +++ b/OsmAnd/res/layout/settings_group_title.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values-ar/phrases.xml b/OsmAnd/res/values-ar/phrases.xml index e5bc657997..bc5277a310 100644 --- a/OsmAnd/res/values-ar/phrases.xml +++ b/OsmAnd/res/values-ar/phrases.xml @@ -117,7 +117,7 @@ شرطة نوع العمل الفني : نافورة نجار - سباك + سباكة معرض سيارات ورشة تصليح السيارات خراطيش الطابعة @@ -382,7 +382,7 @@ الوصول إلى المراحيض بالكراسي المتحركة: نعم الوصول إلى المراحيض بالكراسي المتحركة: لا الوصول إلى دورة المياة: العملاء فقط - طاولة تغيير الحفائض + طاولة تغيير حفائض الأطفال لا توجد طاولة تغيير الحفاض غرفة تغيير الحفاضات الوقت المحدد لوقوف السيارات @@ -563,7 +563,7 @@ مساحة تجارية حقل عنب مزرعة - مرعى أو مرج + مرعى/مرج/روضة قناة مراقبة مرصد @@ -702,7 +702,7 @@ تجميل الاظافر صالون تدليك صالون وشم - التنظيف الجاف + مغسلة ملابس غسيل الملابس تأجير سيارات مشاركة السيارات @@ -1369,7 +1369,7 @@ طب الأطفال الاجتماعي طب التوليد (القيصرية) طب الإدمان - بصريات + نظارات/بصريات علاج النطق الطب الرياضي الوخز بالإبر @@ -1396,7 +1396,7 @@ كافتيريا الخدمات نوع الدراجة النارية - موحد + قياسية النوع محطة Aerialway رافعة بالكرسي @@ -1437,7 +1437,7 @@ مسار الزحلقة الحيوانات المسموح بها الغرض - الوجهة: مدخل + الاتجاه: المدخل قوارب مأجرة بئر نفط شبكات الكريكيت @@ -1569,32 +1569,32 @@ دولفين مكان لتغذية الحيوان قدرة تحمل المكان للماء: متين - بروز - تماس - التماس غير مقبول + بروز طبقات الأرض (تفجر أرضي) + تلامس + لا يتم قبول التلامس خطر خطر مواد نووية - خطر التآكل - خطر الانهيار - طريق زلقة + خطر الهيار/التعرية الأرضية + خطر الانهيار الجليدي + طريق زلق خطر فيضانات حقل الغام - أطلال + أطلال/أنقاض/خرائب فئات الترخيص تل تصليح أحذية نعم فقط - خط أنابيب فرعية - الإرسال + محطة فرعية لخطوط الأنابيب + ‌الإرسال/الدفع التوزيع توزيع ثانوي صناعية - مرحلة انتقالية - جر + ناقل + تغذية النقل (المترو/القطار ..) محول التعويض - ضغط + الضغط قياس صمام مجموعة صمامات @@ -1602,14 +1602,14 @@ ميدان تجمع إنتاج حلويات متجر جملة - مختبرات طبية + مختبر طبي التبرع بالدم قصص مصورة أثري ديني أكاديمي أطفال - جزر مرجانية + جزيرة مرجانية جهاز ارسال رسوم الكترونية رعاية أطفال معلم طبيعي @@ -1618,7 +1618,7 @@ قطار باص مترو انفاق - HOV + مركبات فيها أكثر من شخص ترام عبّارة مصدر الطاقة: الكتلة الحيوية @@ -1739,7 +1739,7 @@ جصاص طبقة الباركيه دهان - أخصائي بصريات + محل نظارات/بصريات حرفة الصناعات المعدنية ناسخ مفاتيح صانع ومصلح المفاتيح @@ -2116,7 +2116,7 @@ سهل مقياس RTSA متضرره من الرياح - فيضة/شجيرات ربيعية + فيضة/روضة براح مستوى العبور معبر خط القطار @@ -2170,7 +2170,7 @@ رطب صعب المشي فيه،قصب اهوار مستنقع - مرعى أو مرج رطب طوال العام + مرعى/مرج رطب طوال العام الطفة البركانية القصدير حجر @@ -2179,7 +2179,7 @@ النوع: ساحة الطوب النوع: زراعة النوع: متلف/محطم السيارات - النوع: مستودع + النوع: مخزن النوع: مصفاة النوع: خشب النوع: صناعة الغاز @@ -2620,7 +2620,7 @@ النوع: قطع الصخور النوع: رمل النوع: قبر حرب - رِجّم (صخور مركومة) علامة + رِجْم، رجوم (صخور مركومة) عتبات مختلفة أو مائلة عتبات غير متساوية عتبات متساوية @@ -2961,4 +2961,702 @@ تركي عالمي تايلندي + برج رادار + (منطقة وقوف جانب الطريق) + سقيفة + على السطح + بنك ميغروس + بطاقة ما بعد التمويل + السحب النقدي: البطاقات الأجنبية + السحب النقدي: الحد الأدنى للشراء + رسوم السحب النقدي: لا + رسوم السحب النقدي: نعم + السحب النقدي: لا يتطلب الشراء + السحب النقدي: لابد من الشراء + عملة السحب النقدي + حد السحب النقدي + نوع السحب النقدي: الدفع الذاتي + نوع السحب النقدي: الدفع + مشغل السحب النقدي + سحب نقدي + السحب النقدي: نعم + العناية بالحيوانات الأليفة + شحن + نجار/صانع أثاث + مخبز + مبلط/تبليط/أرضيات + نجار + مقاولات/بناء + الغذاء الصحي + مدخل القبو + المعينه/المحدد + نعم + المعينه/المحدد + نعم + للتسليم والتوصيل فقط + المعينه/المحدد + للوصول للوجهة فقط + نعم + المعينه/المحدد + نعم + المعينه/المحدد + نعم + المعينه/المحدد + للوصول للوجهة فقط + نعم + المعينه/المحدد + نعم + المعينه/المحدد + نعم + المعينه/المحدد + نعم + المعينه/المحدد + نعم + خاص مسموح بدخوله + المعينه/المحدد + نعم + السماح بدخول المعاقين: لا + الخيول غير مسموح بها + مسموح بالخيول + السماح بدخول مركبات الأجرة: لا + السماح بدخول مركبات الأجرة: محدد + السماح بدخول مركبات الأجرة: نعم + السماح بدخول المركبات الزراعية: لا + السماح بدخول المركبات الزراعية: نعم + السماح بدخول الزلاجات الآلية: لا + السماح بدخول الزلاجات الآلية: خاص + السماح بدخول الزلاجات: لا + السماح بدخول الزلاجات: نعم + السماح بدخول مدربي القيادة: لا + السماح بدخول مدربي القيادة: نعم + السماح بدخول حافلات السياح: نعم + السماح بدخول حافلات السياح: لا + السماح بدخول حافلات السياح: محدد + السماح بدخول الحافلات: لا + السماح بدخول مركبات الخدمات العامة: لا + السماح بدخول مركبات الخدمات العامة: محدد + السماح بدخول مركبات الخدمات العامة: لا + السماح بدخول المقطورات: لا + السماح بدخول البيوت المتنقلة: لا + السماح بدخول الكرفانات: لا + السماح بدخول المشاة: للعملاء فقط + السماح بدخول المشاة: للعبور إلى الوجهة فقط + السماح بدخول المشاة: لا + السماح بدخول المشاة: خاص + السماح بدخول المشاة: نعم + السماح بدخول الخيول: الخاصة بالغابات + السماح بدخول الخيول: للعبور إلى الوجهة + السماح بدخول الخيول: خاص + السماح بدخول الدراجات: للعملاء فقط + السماح بدخول الدراجات: للعبور إلى الوجهة + السماح بدخول الدراجات: بدون قيادتها (سحبها مشياً) + السماح بدخول الدراجات:خاص + السماح بدخول الدراجات الآلية:لا + السماح بدخول الدبابات الصغيرة:لا + السماح بدخول الدراجات النارية:لا + السماح بدخول الدراجات النارية:خاص + السماح بدخول المركبات الصغيرة:لا + السماح بدخول المركبات الكبيرة:غير ملائم + السماح بدخول المركبات الكبيرة:غير مناسب + السماح بدخول المركبات الكبيرة:الزراعية + السماح بدخول المركبات الكبيرة:لا + السماح بدخول المركبات الكبيرة:خاص + السماح بدخول المركبات الآلية:الزراعية + السماح بدخول المركبات الآلية:الخاصة بالغابات + السماح بدخول المركبات الآلية: للتسليم فقط + السماح بدخول المركبات الآلية:العسكرية + السماح بدخول المركبات الآلية:العملاء فقط + السماح بدخول المركبات الآلية:للوصول إلى الوجهة فقط + السماح بدخول المركبات الآلية:لا + السماح بدخول المركبات الآلية:خاص + السماح بدخول المركبات الآلية:نعم + السماح بدخول السيارات: الخاصة بالغابة + السماح بدخول السيارات: العملاء + ‏‏ خاص مسموح بدخوله + خاص مسموح بدخوله + السماح بدخول المشاة: خاص مسموح بدخوله + السماح بدخول الخيول: خاص مسموح بدخوله + السماح بدخول الدرجات: خاص مسموح بدخوله + السماح بدخول المركبات الآلية: خاص مسموح بدخوله + السماح بدخول السيارات: خاص مسموح بدخوله + السماح بدخول السيارات: للعبور للوجهة + السماح بدخول السيارات: لا + السماح بدخول السيارات:خاص + السماح بدخول السيارات: + السماح بدخول المركبات: الخاصة بالغابات + السماح بدخول المركبات: لتسليم الطلبات + السماح بدخول المركبات: العسكرية + السماح بدخول المركبات: العملاء فقط + السماح بدخول المركبات: خاص مسموح بدخوله + السماح بدخول المركبات: للعبور للوجهة + السماح بدخول المركبات: لا + السماح بدخول المركبات: خاص + السماح بدخول المركبات: نعم + مكتب سيارات الأجرة + رسوم على طاولة تغيير الأطفال: لا + رسوم على طاولة تغيير الأطفال: نعم + عدد طاولات تغيير الأطفال + موقع طاولة تغيير للأطفال: دورة مياة للجنسين + موقع طاولة تغيير للأطفال: دورة مياة النساء + موقع طاولة تغيير للأطفال: دورة مياة الرجال + موقع طاولة تغيير للأطفال: غرفة + طاولة تغيير للأطفال: محدودة (غير رسمية) + طاولة تغيير للأطفال: لا + طاولة تغيير للأطفال: نعم + الموقع (وصف المكان) + الخطر: التلوث + الخطر: حقل ألغام + الخطر: انهيار جليدي + الخطر: فيضان + الخطر: نووي + الخطر: سقوط الصخور + خطر: تآكل/تعرية + صندوق الطوارئ + كائن محذوف + شعلة الغاز ؛ مداخن مضيئة + 3B* + 3B + 3A* + 3A + 2B* + 2B + 2A* + 2A + 1B* + 1B + 1A* + 1A + n/c* + n/c + شوكو + نيما 14-50 + نيما 14-30 + نيما 5-20 + نيما 5-15R + تسلا رودستر + شاحن تسلا + معيار تسلا + شاديمو + النوع 3 + النوع 2 كومبو + النوع 2 + النوع 1 كومبو + النوع 1 + CEE الأحمر 125A + CEE الأحمر 64 أ + CEE الأحمر 32A + CEE الأحمر 16A + CEE الأزرق + متجر قوارب + متجر موقد/مشب + متجر زراعي + أغذية مجمدة + النوع: مرعى + النوع: انتقالي + النوع: دائم + النوع: زراعي + قطر القمة + محيط + طرق التسلق + تسلق قمة الجذوع: لا + تسلق قمة الجذوع: نعم + اتجاه الجدار: شمال غرب + اتجاه الجدار: غرب + اتجاه الجدار: جنوب غرب + اتجاه الجدار: جنوب + اتجاه الجدار: جنوب شرق + اتجاه الجدار: شرق + اتجاه الجدار: شمال شرق + اتجاه الجدار: شمال + المراسي الثابتة: لا + المراسي الثابتة: نعم + جودة التسلق: هشة + جودة التسلق: ثابت + تسلق الصخور: الرخام السماقي + تسلق الصخور: النيس + تسلق الصخور: الكوارتز + تسلق الصخور: الحجر الرملي + تسلق الصخور: الجرانيت + تسلق الصخور: الحجر الجيري + طول الحد الأقصى للتسلق + طول الحد الأدنى للتسلق + طول مساحة التسلق + التسلق الفردي في المياه العميقة: لا + التسلق الفردي في المياه العميقة: نعم + مختلط: لا + مختلط: نعم + الجليد: لا + الجليد: نعم + طرق متعددة : لا + طرق متعددة: نعم + تقليدي: لا + تقليدي: نعم + حبل علوي: لا + حبل علوي: نعم + بولدرينغ: لا + بولدرينغ: نعم + الرياضة: لا + الرياضة: نعم + الرمز البريدي + صندوق الرسائل + مستودع + حجم الخريطة: المنطقة + حجم الخريطة: المدينة + حجم الخريطة: الموقع + نوع الخريطة: الطبوغرافية التي توضح معالم الاتجاهات + نوع الخريطة: مخطط + نوع الخريطة: طبوغرافية + مخرج محطة الشحن + التيار/أمبير + رسوم وقوف السيارات: لا + رسوم وقوف السيارات: نعم + شاحنة: لا + شاحنة: نعم + المقبس: CEE الأحمر 32A: التيار + المقبس: CEE الأحمر 64A: التيار + ‍المقبس: CEE الأحمر 125A: التيار + مأخذ التوصيل: النوع 1: التيار + مأخذ التوصيل: نوع 1 التحرير والسرد: التيار + مأخذ التوصيل: النوع 2: التيار + المقبس: نوع 2 التحرير والسرد: التيار + مأخذ التوصيل: النوع 3: التيار + المقبس: CHAdeMO: التيار + المقبس: تيسلا رودستر: التيار + المقبس: نيما 14-50: التيار + المقبس: CEE الأحمر 16A: التيار + المقبس: CEE الأزرق: التيار + سكوتر: لا + سكوتر: نعم + الدراجة: لا + الدراجة: نعم + السيارة: لا + السيارة: نعم + المقبس: AS / NZS 3112: الإخراج + المقبس: AS / NZS 3112: التيار + المقبس: AS / NZS 3112 + المقبس: BS 1363: الإخراج + مأخذ التوصيل: BS 1363: التيار + المقبس: BS 1363 + المقبس: شوكو: الإخراج + المقبس: Schuko: التيار + المقبس: شوكو + المقبس: نيما 14-50: الإخراج + المقبس: نيما 14-30 + المقبس: نيما 14-30: الإخراج + المقبس: نيما 14-30: التيار + المقبس: نيما 14-30 + المقبس: نيما 5-20: الإخراج + المقبس: نيما 5-20: التيار + المقبس: نيما 5-20 + المقبس: نيما 5-15R: الإخراج + المقبس: نيما 5-15R: التيار + المقبس: نيما 5-15R + المقبس: تسلا رودستر: الإخراج + المقبس: تسلا رودستر + المقبس: تسلا شاحن: الإخراج + المقبس: تسلا شاحن: التيار + المقبس: تسلا سوبر تشارج + المقبس: معيار تسلا: الإخراج + المقبس: معيار تسلا: التيار + المقبس: معيار تسلا + مأخذ التوصيل: CHAdeMO: الإخراج + المقبس: شاديمو + مأخذ التوصيل: النوع 3: الإخراج + المقبس: النوع 3 + المقبس: النوع 2 التحرير والسرد: الإخراج + المقبس: نوع 2 كومبو + مأخذ التوصيل: نوع 2: الإخراج + المقبس: النوع 2 + المقبس: نوع 1 التحرير والسرد: الإخراج + المقبس: نوع 1 كومبو + مأخذ التوصيل: النوع 1: الإخراج + المقبس: النوع 1 + المقبس: CEE الأحمر 125A: الإخراج + المقبس: CEE الأحمر 125A + المقبس: CEE الأحمر 64A: الإخراج + المقبس: CEE الأحمر 64A + المقبس: CEE الأحمر 32A: الإخراج + المقبس: CEE الأحمر 16A + المقبس: CEE الأحمر 16A: الإخراج + المقبس: CEE الأحمر 16A + المقبس: CEE الأزرق: الإخراج + المقبس: CEE الأزرق + عائلات متعددة + العائلة + المجتمع + مياه معبأة + خزان ماء + نقل المياه بالشاحنات + الثقب + مضخة + المياه الجارية + خط انابيب + بئر ماء + أكواتابس + التناضح العكسي + الكلور + بدون + نقطة GPX + الغاز الطبيعي المسال + متجر البندق + خلية نحل + الجدول الزمني + في الوقت الحقيقي + تأخير + نعم + لوحة المغادرين: لا + مصعد + كتلة المدينة + محافظة + صندوق العطايا + أسهم: لا + نعم + نعم + الاهتزاز: لا + حالة المضخة: شعاع مفقود + شفط + مضغوط + مياه جوفية + أنابيب + شبكة تعبئة مياه الشرب + إعادة تعبئة مياه الشرب:لا + نعم + عائق + مستوى الماء: أقل من مستوى الماء + مستوى الماء: فوق متوسط مستوى الماء + مستوى الماء: عائم + مستوى الماء: فيضانات + منسوب الماء: متقاذف/متلاطم + مستوى الماء: يغطي + مستوى الماء: جاف + مستوى الماء: مغمور + مستوى الماء: جزء مغمور + غير صحيح + بدائي + متباين اللون + فقط عندما يسمح بالمشي + لا + نعم + نوع الكشك + كشك + لا + نعم + قاعدة الصيد + رقم مرجع الزحلقة + مركز البولينج + متجر الأمن + إنقاذ الجبال + بينتبول (كرة الطلاء) + دراجة الشبح + عدد الانفجارات + خامل + نشط + في سبات + منطفئ/خامد + آخر ثوران بركاني + طينيه + قبة الحمم البركانية + فوه بركانيه كبيرة + لكن + درع + ستراتوفوكانو + سكوريا + الرابط + أماكن لوقوف السيارات + قبر + جنس المجتمع: ذكر + جنس المجتمع: أنثى + لا + نعم + حمام القدم + بحيرة + نهر + حراري + حمام + أونسن + ينبوع ساخن + بوستبنك + جيروكارد + قدرة تحمل المكان للماء: للطوارئ + معطل + يحتاج إلى صيانة + مقيد + مغلق + مفتوح + الرؤية: المنطقة (أعلى من 50 متر) + الرؤية: الشارع (10-50 متر) + الرؤية: منزل (10 متر) + الموقع: المدخل + الموقع: الجدار + الموقع: الجسر + الموقع: كشك + الموقع: منصة + الموقع: داخلي + الموقع: في الهواء الطلق + الموقع: السطح + الموقع: السقف + الموقع: في الهواء + الموقع: فوق الأرض + الموقع: تحت الماء + الموقع: تحت الارض + شبكة معدنية + DecoTurf + العشب الصناعي + طرطان + طين + منطقة جبلية + أخدود/تلعة + الخدمات الاجتماعية + الضمان الاجتماعي + أرشيف + الشبكة + كانوي: لا + كانوي: نعم + زوارق الكاياك: لا + زوارق الكاياك: نعم + زورق: لا + زورق: نعم + المراكب الشراعية: لا + المراكب الشراعية: نعم + جيتسكي: لا + جيتسكي: نعم + الدواسات: لا + الدواسات: نعم + المراكب: لا + المراكب: نعم + القوارب: لا + القوارب: نعم + تأجير قوارب + أسرة/سرير + الحجز: للأعضاء فقط + الحجز: لا + الحجز: نعم + الحجز المسبق: موصى به + الحجز المسبق: مطلوب + غرفة الشتاء: لا + غرفة الشتاء: نعم + الاتجاه: لأسفل + اتجاه: لأعلى + الاتجاه: عكس اتجاه عقارب الساعة + الاتجاه: اتجاه عقارب الساعة + الاتجاه: للخلف + الاتجاه: إلى الأمام + الاتجاه: الشمال والشمال الغربي + الاتجاه: شمال غربي + الاتجاه: الغرب والشمال الغربي + الاتجاه: الغرب + الاتجاه: الغرب والجنوب الغربي + الاتجاه: جنوب غربي + الاتجاه: الجنوب والجنوب الغربي + الاتجاه: الجنوب + الاتجاه: جنوب-جنوب شرق + الاتجاه: جنوب شرق + الاتجاه: شرق وجنوب شرق + الاتجاه: شرق + الاتجاه: شرق - شمال شرق + الاتجاه: شمال شرقي + الاتجاه: الشمال والشمال الشرقي + الاتجاه: شمال + ميناء فضائي + إطلاق السراح: لا + إطلاق السراح: نعم + التبني: لا + التبني: نعم + مالك + مزدوج + الطرق الوعره + المروحيه + دراجة رياضية + سكوتر + ملابس الدراجات النارية: لا توجد + ملابس الدراجات النارية + إطارات: لا + اطارات + قطع غيار: لا + قطع غيار + إصلاح: لا + إصلاح + تأجير: لا + تأجير + المبيعات: مستعملة + المبيعات: نعم ، مستعملة + مبيعات: لا + مبيعات + منصة + زواحف + صقور + مطير (قفص) + طيور + حديقة سفاري + سياج + حديقة حيوانات برية + حديقة الحيوانات الأليفة + طوق النجاة + مدرسة لغة + مخيم للأطفال + إصلاح الإلكترونيات: الهاتف + إصلاح الإلكترونيات: الأجهزة + إصلاح الإلكترونيات: أجهزة الكمبيوتر + مكتب تجهيزات الطاقة + نعم + مساحة عمل مشتركة + محطة الشحن + البناء: مخفي + البناء: قبة + البناء: طبق + البناء: قائم بذاته + البناء: شبكة فولاذية + النوع: إسطبل مفتوح + النوع:مربط خيول + كومة فحم + متجر الأجهزة + تاريخ الانتهاء + صخرة + دورة + إلكتروني + إبرة + دفتر ملاحظات + رمز + نقطة الختم + نقطة تفتيش للمشاة/الهايكنق + متوسط الميلان + أدنى نقطة + أعلى نقطة + اللسان الجليدي + بقايا + الجرف + صخرة + انهيار الجليد + معلقة + جبل + مياه المد + منفذ + وادي + هضبة + الحقل الجليدي + الغطاء الجليدي + الصعوبة + رقم الكابل + فيا فيراتا (مسار الحديد) + مغامرة التسلق + المسار الإنزلاقي + كفرات/جنوط + الإطارات + إصلاح مكاين/محركات + إصلاح قير + ميزان/وزن أذرعة ومقصات + شكمان/كاتم صوت/دبات + تصليح شاحنات ومعدات ثقيلة + زجاج + الكهربائية + سمكرة وتعديل جسم السيارة + تبريد/مكيفات + بطاريات + قطع غيار السيارات + تشخيص/فحص + مبيعات السيارات الجديدة + فرامل + مبيعات السيارات المستعملة + تغيير زيت + إصلاح السيارات + مكتب مرافق المياه + شواية: نعم + نقطة تسليم المحل + اسم منحدرات النهر + فخار + متجر الأرضيات + منخفض + متوسط + عالي + منخفض + متوسط + عالي + منخفض + متوسط + عالي + منخفض + متوسط + عالي + منخفض + متوسط + عالي + منخفض + متوسط + عالي + AS/NZS 3112 + BS 1363 + طاولة نزهة + وجهة نظر + منطقة دينية + الوصول إلى الإنترنت: رسوم مفروضة + الوصول إلى الإنترنت: نعم + الوصول إلى الإنترنت: خدمة + الوصول إلى الإنترنت: عام + ولوج الإنترنت: سلكي + "ولوج الإنترنت: terminal" + ولوج الإنترنت: wlan + ماهايانا + ماروني + شينجون شو + ارثوذكسي قبطي + موحد + الأرثوذكسية الإثيوبية التوحيدية + الأرثوذكسية الرومانية + عالم + الأرثوذكسية الجورجية + كنيسة المسيح المتحدة + كنيسة المسيح + قديسي اليوم الأخير + اصلاح + رسولي + رسولي أرميني + روحاني + الأرثوذكسية الصربية + المؤمنون القدامى + تجمعي + ناصري + سبتي + غير طائفي + تجميعات الإله + الأرثوذكسية البلغارية + كواكر + مينونايت + توحيد + كنيسة إغليسيا ني كريستو + جيش الخلاص + كنيسة اسكتلندا + الكنيسة الإصلاحية الموحدة + التبت + كاثوليكي يوناني + متحد + الأسقفية + كنيسة إنجلترا + رسولي جديد + سبتي (مؤمن برجوع المسيح في اليوم السابع) + تم إصلاحه + الأرثوذكسية اليونانية + شهود يهوه + المورمون + الأنجليكانية + الزرادشتية + ديانة تينريكيو اليابانية + علم السايونتولوجيا + البهائية + الديانة الجاينية الهندية + التوحيد الكوني + قطار (سياحي) + أرجوحة ملاهي دوارة + التزحلق الصيفي + قطار الملاهي + متاهة + دائري + عجلة فيريس/ملاهي + حيوان (جذب) + جولة تسلية + شيء سياحي + جذب سياحى + منجم تاريخي + حطام سفينة + حجر الشاهد القائم الروني + دبابة تاريخية \ No newline at end of file diff --git a/OsmAnd/res/values-ar/strings.xml b/OsmAnd/res/values-ar/strings.xml index 26b1bd66e3..e7f575f576 100644 --- a/OsmAnd/res/values-ar/strings.xml +++ b/OsmAnd/res/values-ar/strings.xml @@ -471,7 +471,7 @@ إفريقيا آسيا أستراليا و أوقيانوسيا - الملاحة + التوجيه مع الطرق ضبط خاص لكل وضع من أوضاع الملاحة. إدارة بيانات الخرائط إعدادات عامة @@ -1153,7 +1153,7 @@ حذف إجراء التعديلات وقت وقوف السيارات يقتصر على - أقل + تدلي قائمة منبسطة تعديل OSM فارغ %1$s @@ -2454,7 +2454,7 @@ تصفح الخريطة وإضافة نقاط قياس المسافة الرجاء إضافة نقطة واحدة على الأقل. - اسم مسار الـGPX : + اسم مسار GPX : عرض على الخريطة بعد الحفظ إضافة نقطة حفظ نقطة GPX @@ -3329,7 +3329,7 @@ جولة تزلج طرق لجولات التزلج. تزلج - منحدرات للاستخدام الزلاجات. + منحدرات لاستخدام الزلاجات. السماح بالمسارات المتوسطة طرق أكثر صعوبة مع أقسام أكثر حدة. بعض العقبات التي ينبغي تجنبها. السماح للطرق المتقدمة @@ -3909,10 +3909,10 @@ التوجيه على مرحلتين لملاحة السيارة. تطوير النقل العام المحلي قم بالتبديل إلى Java (الآمن) حساب توجيه النقل العام - قم بتسجيل الدخول إلى OAuth لاستخدام ميزات osmedit + سجّل الدخول باستخدام OAuth لاستخدام ميزات osmedit تسجيل الدخول عبر OAuth مسح رمز OpenStreetMap OAuth - تسجيل الخروج بنجاح + تم تسجيل الخروج تم استيراد الملف بالفعل في أوسماند استخدام خوارزمية توجيه من مرحلتين A* %1$s البيانات المتوفرة فقط على الطرق ، تحتاج إلى حساب طريق باستخدام \"الطريق بين النقاط\" للحصول عليها. @@ -3940,12 +3940,12 @@ انتهت صلاحية اشتراك OsmAnd Live تم إيقاف اشتراك OsmAnd Live مؤقتًا اشتراك OsmAnd Live معلق - تسجيل الدخول إلى خريطة الشارع المفتوح - تسجيل الدخول إلى OpenStreetMap.org - تحتاج إلى تسجيل الدخول لرفع التغييرات الجديدة أو المعدلة. + تسجيل الدخول لخريطة الشارع المفتوح + تسجيل الدخول إلى خريطة الشارع المفتوح + قم بتسجيل الدخول لرفع التغييرات الجديدة أو المعدلة. \n -\nيمكنك تسجيل الدخول باستخدام طريقة التفويض الآمنة أو استخدام تسجيل الدخول وكلمة المرور. - استخدام تسجيل الدخول وكلمة المرور +\nإما باستخدام المصادقة أو باستخدام اسم المستخدم وكلمة المرور. + سجل الدخول باسم المستخدم وكلمة المرور الحساب تسجيل الدخول \"إمكانية التتبع\" تعني أن التتبع لا يظهر في أي قوائم عامة ولكن نقاط التتبع المعالجة مع طوابع زمنية صادرة عنها(التي لا يمكن أن تكون مرتبطة بك مباشرة) ستظهر خلال التنزيلات من واجهة برمجة التطبيقات GPS API العامة. @@ -3953,19 +3953,37 @@ أرسل ملف GPX إلى OpenStreetMap أدخل العلامات مفصولة بفاصلة. \"خاص\"يعني أن التتبع لن يظهر في أي قوائم عامة ، ولكن نقاط التتبع الصادرة عنه ستظل متاحة من خلال واجهة برمجة تطبيقات GPS API العامة بدون طوابع زمنية ولكن لن يتم ترتيبها ترتيبًا زمنيًا. - قم بتسجيل الدخول باستخدام OpenStreetMap + تسجيل الدخول عبر الشارع المفتوح عام يعني أنه سيتم عرض التتبع بشكل عام في تتبعات GPS الخاصة بك وفي قوائم تتبع GPS العامة. البيانات المقدمة عبر API لا تشير إلى صفحة التتبع الخاصة بك. الطوابع الزمنية لنقاط التتبع غير متاحة من خلال واجهة برمجة تطبيقات GPS API العامة، والنقاط غير مرتبة ترتيبًا زمنيًا. ومع ذلك، لا يزال المستخدمون الآخرون قادرين على تنزيل التتبع الأولي من قائمة التتبع العامة وأي طوابع زمنية مضمنة فيه. متعرف عليه يعني أنه سيتم عرض التتبع بشكل عام في تتبعات GPS الخاصة بك وفي قوائم تتبع GPS العامة، أي سيتمكن المستخدمون الآخرون من تنزيل التتبع الأولي وربطه باسم المستخدم الخاص بك. ستشير البيانات التي يتم تقديمها عبر API نقاط التتبع إلى صفحة التتبع الأصلية الخاصة بك. الطوابع الزمنية لنقاط التتبع متاحة من خلال واجهة برمجة تطبيقات GPS API العامة. أغلاق ملاحظة OSM تعليق ملاحظة OSM - يمكنك تسجيل الدخول باستخدام طريقة OAuth الآمنة أو استخدام تسجيل الدخول وكلمة المرور الخاصة بك. + قم بتسجيل الدخول باستخدام طريقة المصادقة الآمنة أو استخدم اسم المستخدم وكلمة المرور. إضافة صورة سجل في \nOpenPlaceReviews.org - يتم توفير الصور من خلال مشروع البيانات المفتوحة OpenPlaceReviews.org. من أجل رفع الصور الخاصة بك، تحتاج إلى الاشتراك بالموقع. + قم بتسجيل الدخول إلى موقع مشروع البيانات المفتوحة OpenPlaceReviews.org لرفع المزيد من الصور. إنشاء حساب جديد لدي حساب بالفعل كاياك (قوارب صغيرة فردية) زورق سجل البحث + جهازك يحتوي على %1$s فقط متاحة . الرجاء إخلاء بعض المساحة أو إلغاء تحديد بعض العناصر للتصدير. + المصادر + حجم الملف التقريبي + حدد البيانات التي سيتم تصديرها إلى الملف. + مطلوب للاستيراد + لا يوجد مساحة كافية + أضف إلى مابيلاي + إضافة إلى OpenPlaceReviews + ويعرض صورًا من عدة مصادر: +\nOpenPlaceReviews - صور POI ؛ +\nMapillary - صور على مستوى الشارع ؛ +\nالويب / ويكيميديا - صور POI المحددة في بيانات OpenStreetMap. + حدد المجموعات التي سيتم استيرادها. + حدد العناصر التي سيتم استيرادها. + قم بالتبديل لاستخدام dev.openstreetmap.org بدلاً من openstreetmap.org لاختبار تحميل OSM Note / POI / GPX. + استخدم dev.openstreetmap.org + لا يمكن تحميل الصورة، من فضلك، حاول مرة أخرى في وقت لاحق + تحديد صورة \ No newline at end of file diff --git a/OsmAnd/res/values-az/strings.xml b/OsmAnd/res/values-az/strings.xml index dfafcf937d..42fe8796e1 100644 --- a/OsmAnd/res/values-az/strings.xml +++ b/OsmAnd/res/values-az/strings.xml @@ -1700,8 +1700,8 @@ Proqramı növbəti dəfə başlatdığınızda qrup yox olacaq. Xəritədə oxları göstər Xəritə işarələrindən sil - azalan - artan + Z-A + A-Z Əlavə edildi Sırala: Bütün xəritə işarələri tarixçəyə daşındı @@ -2069,7 +2069,7 @@ Vikisəyahət Üst panel %1$s düzəliş, cəmi %2$s mBTC - Ye + Yeni marşrut yarat Hazırdır Naviqasiya profili OsmAnd Live məlumatları @@ -2090,4 +2090,84 @@ İstifadəçi adı Şəkil əlavə et Yeni hesab yarat + Bərpa et + t + + Daşıma + Xəritələri daşı + %1$d fayl kopyalandı (%2$s). + %1$d fayl daşındı (%2$s). + GPS axtarılır + Proqram profilləri + Profil adı + İcazə ver + Xeyr, təşəkkürlər + İkon + %s saxlandı + Standart + Pulsuz + Üç ay + İl + İl + İl + Ay + Ay + Ay + Həftə + Həftə + Həftə + Gün + Gün + Gün + OsmAnd parametrləri + Qovluq… + %1$s GB boş (%2$s GB-dan) + %1$s kB + %1$s MB + %1$s GB + %1$s TB + Xəritələr + Hesabla + Bütün xəritələri yenilə + + %s endirilir + OSM + İstifadəçi adı və şifrə + Bildiriş + %1$s/%2$s + %1$s — %2$s — %3$s + Menyu + Parametrləri aç + Profillər + Bucaq + Bucaq: %s° + Xüsusi profil + Yeni profil saxlanılır + %2$s-dən %1$s + Dillər + Dil + Bütün dillər + Xüsusi rəng + %1$s / %2$s + OsmAnd + Mapillary + Favoritlər + Naviqasiya profilləri + Profil əlavə et + Proqram profilini dəyiş + Hər zaman + SQLiteDB faylı + Hamısı silinsin\? + Aktiv saxla + Sil + ton + metr + Mapillary-ni göstər/gizlət + Mapillary-ni gizlət + Mapillary-ni göstər + %1$s silindi + Sil və yenidən başlat + Vikipediya xəritələrini endir + Bağlanmış OSM qeydi + Xüsusi + Son düzəliş \ No newline at end of file diff --git a/OsmAnd/res/values-ca/strings.xml b/OsmAnd/res/values-ca/strings.xml index a8b5d32da2..7205f99cb0 100644 --- a/OsmAnd/res/values-ca/strings.xml +++ b/OsmAnd/res/values-ca/strings.xml @@ -89,7 +89,7 @@ Utilitza mapes en línia (les tessel·les es baixen i es desen a la tarja de memòria). Mapes en línia Seleccioneu les fonts de mapes de tessel·les en línia o a la memòria cau. - "Fa disponible directament des OsmAnd les característiques d\'accessibilitat del dispositiu. Us permet, per exemple, ajustar la velocitat de la veu sintetitzada, configurar la navegació amb cursors, utilitzant un ratolí de bola per controlar el zoom o rebre notificacions amb veu sintetitzada, per exemple per anunciar automàticament la vostra posició." + Fa disponible directament des OsmAnd les característiques d\'accessibilitat del dispositiu. Us permet, per exemple, ajustar la velocitat de la veu sintetitzada, configurar la navegació amb cursors, utilitzant un ratolí de bola per controlar el zoom o rebre notificacions amb veu sintetitzada, per exemple per anunciar automàticament la vostra posició. Gestor de connectors Cerca de PDI (punt d\'interès) Gestor de connectors @@ -351,55 +351,38 @@ Carpeta d\'emmagatzematge de dades OsmAnd (OSM Automated Navigation Directions) \n -\n \nOsmAnd és una aplicació de navegació feta amb programari de codi obert amb accés a una gran varietat de dades globals d\'OSM. Totes les dades dels mapes (siguin mapes vectorials o de tessel·les), es poden desar a la targeta de memòria del telèfon pel seu en desconnexió. També calcula rutes, amb connexió o sense, incloent l\'orientació per veu. \n -\n -\nAlgunes de les característiques principals: -\n -\n- Funcionament complet en desconnexió (desa localment els mapes vectorials i de tessel·les baixats) -\n -\n- Mapes vectorials compactes de tot el món per usar en desconnexió -\n -\n- Baixada de mapes nacionals o regionals directament des de l\'aplicació -\n -\n- Diverses capes de mapes alhora, com traces GPX o de navegació, punts d\'interès, Preferits, parades de transport públic, etc. amb nivell d\'opacitat personalitzada -\n -\n- Cerca, fora de línia, d\'adreces i llocs -\n +\nAlgunes de les característiques principals: +\n- Funcionament complet en desconnexió (desa localment els mapes vectorials i de tessel·les baixats) +\n- Mapes vectorials compactes de tot el món per usar en desconnexió +\n- Baixada de mapes nacionals o regionals directament des de l\'aplicació +\n- Diverses capes de mapes alhora, com traces GPX o de navegació, punts d\'interès, Preferits, parades de transport públic, etc. amb nivell d\'opacitat personalitzada +\n- Cerca, fora de línia, d\'adreces i llocs \n- Càlcul de rutes fora de línia fins per distàncies d\'abast mitjà. +\n- Modalitats opcionals de cotxe, bicicleta i vianant +\n- Canvi automàtic de vista diürna a nocturna +\n- Escala del mapa en funció de la velocitat +\n- Orientació del mapa segons la brúixola o la direcció del moviment +\n- Indicació de carril, velocitat màxima permesa, veus enregistrades i/o sintetitzades \n -\n- Modalitats opcionals de cotxe, bicicleta i vianant +\nLimitacions d\'aquesta versió gratuïta de OsmAnd: +\n- Limitació en el nombre de mapes baixats +\n- No hi ha accés als PDIs de la Viquipèdia sense connexió \n -\n- Canvi automàtic de vista diürna a nocturna -\n -\n- Escala del mapa en funció de la velocitat -\n -\n- Orientació del mapa segons la brúixola o la direcció del moviment -\n -\n- Indicació de carril, velocitat màxima permesa, veus enregistrades i/o sintetitzades -\n -\n -\nLimitacions d\'aquesta versió gratuïta de OsmAnd: -\n -\n- Limitació en el nombre de mapes baixats -\n -\n- No hi ha accés als PDIs de la Viquipèdia sense connexió -\n -\n \nOsmAnd es desenvolupa activament i el nostre projecte i el seu progrés continu depenen de donacions pel desenvolupament i proves de noves funcions. Si us plau, considereu la compra d\'OsmAnd+ o patrocinar una nova característica concreta, o fer una donació genèrica a la pàgina https\\\\osmand.net. - "OsmAnd+ (OSM Automated Navigation Directions) + OsmAnd+ (OSM Automated Navigation Directions) \n \nL\'OsmAnd+ és un programari de navegació de codi obert amb accés a una gran varietat de dades globals de OSM. Totes les dades de mapes (mapes de tessel·les o vectorials) poden emmagatzemar-se a la targeta de memòria del telèfon pel seu ús sense connexió. També proporciona la funcionalitat de càlcul de rutes sigui amb connexió o sense, incloent orientació per veu. \n \nL\'OsmAnd+ és la versió de pagament; comprant-la esteu donant suport al projecte, financeu el desenvolupament de noves funcions i rebreu les darreres actualitzacions. \n \nAlgunes de les característiques centrals són: -\n- Funcionalitat completa fora de línia (desa en el dispositiu d\'emmagatzemament els mapes vectorials i de mosaic baixats) +\n- Funcionalitat completa fora de línia (desa en el dispositiu d\'emmagatzemament els mapes vectorials i de mosaic baixats) \n- Mapes vectorials compactes de tot el món disponibles \n- Baixada il·limitada de mapes nacionals o regionals directament des de l\'aplicació \n- Disponibilitat sense connexió dels PDI baixats prèviament de Viquipèdia, ideal per fer turisme -\n- Possibilitat de superposar diverses capes de mapes simultànies, com traces GPX o de navegació, Punts d\'interès, Favorits, corbes de nivell, parades de transport públic, mapes addicionals amb nivell de transparència ajustable +\n- Possibilitat de superposar diverses capes de mapes simultànies, com traces GPX o de navegació, Punts d\'interès, Favorits, corbes de nivell, parades de transport públic, mapes addicionals amb nivell de transparència ajustable \n \n- Cerca fora de línia d\'adreces i llocs (PDIs) \n- Càlcul de rutes fora de línia per distàncies d\'abast mitjà @@ -408,7 +391,7 @@ \n- Escala automàtica del mapa segons la velocitat \n- Orientació del mapa segons la brúixola o la direcció del moviment \n- Indicacions de carril, velocitat màxima permesa, veus enregistrades i sintetitzades -\n" +\n Seleccioneu el nivell mínim de zoom per mostrar el mapa si està disponible. Caldrà el fitxer SRTM separat: Aquest connector mostra la configuració de característiques per al desenvolupament i depuració com la verificació o simulació de rutes, el rendiment del renderitzat o les indicacions de veu. Aquestes configuracions s\'adrecen a desenvolupadors i no són d\'utilitat per a un usuari normal. En consonància amb la configuració del sistema Android @@ -578,7 +561,7 @@ Mapa superposat Temps de sincronització del mapa seguint la nova posició. Mapa de fons - Escolliu mapa de fons. + Escolliu mapa de fons Escolliu el mapa superposat Llengua de visualització de l\'aplicació (s\'actualitzarà quan reinicieu OsmAnd). ft @@ -605,7 +588,7 @@ El mateix que el dispositiu Afegir nova regla No hi ha dades PDI fora de linía per a aquesta area - "No s\'ha pogut actualitzar la llista local de PDIs" + No s\'ha pogut actualitzar la llista local de PDIs. Max. zooms en linía Servei de navegació Baixant llista de les regions disponibles… @@ -641,7 +624,7 @@ Edita el PDI Elimina el PDI Crea un PDI - "Gràcies per utilitzar l\'OsmAnd. Baixeu informació regional fora de línia a través de \'Configuració\' → \'Gestió de fitxers de mapes\' per veure mapes, situar adreces, buscar els PDIs, trobar transports públics i més." + Gràcies per utilitzar l\'OsmAnd. Baixeu informació regional fora de línia a través de \'Configuració\' → \'Gestió de fitxers de mapes\' per veure mapes, situar adreces, buscar els PDIs, trobar transports públics i més. El mapa mundial de fons necessari per les funcionalitats bàsiques està a la cua de baixades. Mostra paràmetres per activar el seguiment i la navegació en procés de fons mitjançant l\'activació periòdica del dispositiu GPS (amb la pantalla apagada). Preferències relatives a l\'accessibilitat. @@ -690,7 +673,7 @@ Seleccioneu un paquet de guiatge de veu Ajusteu el criteri de commutació entre el mode nocturn i el diürn. Aquest mapa podria no haver-se baixat - No s\'ha pogut dibuixar l\'àrea triada + No s\'ha pogut dibuixar l\'àrea triada. Utilitza la ubicació… El renderitzador s\'ha carregat No hi ha punts Preferits @@ -701,8 +684,8 @@ Transport públic Emergències Restaurants - "Permet fer contribucions a OSM com la creació o modificació de PDIs d\'OSM, obrir o comentar anotacions OSM i aportar fitxers enregistrats GPX amb OsmAnd en subministrar el vostre usuari i contrasenya. OpenStreetMap.org és un projecte gestionat per una comunitat, de domini públic i de cartografia global." - "La llengua seleccionada no està suportada per el motor de TTS (text a veu) d\'Android instal·lat, s\'usarà la llengua del TTS per defecte. Voleu buscar un altre motor TTS a la botiga\?" + Permet fer contribucions a OSM com la creació o modificació de PDIs d\'OSM, obrir o comentar anotacions OSM i aportar fitxers enregistrats GPX amb OsmAnd en subministrar el vostre usuari i contrasenya. OpenStreetMap.org és un projecte gestionat per una comunitat, de domini públic i de cartografia global. + La llengua seleccionada no està suportada per el motor de TTS (text a veu) d\'Android instal·lat, s\'usarà la llengua del TTS per defecte. Voleu buscar un altre motor TTS a la botiga\? Comparteix l\'ubicació usant Format de mapa «{0}» obsolet, no s\'admet Màxim zoom en precàrrega @@ -711,7 +694,7 @@ Resultats de transport ({0} al destí): La llibreria seleccionada de missatges de veu no està disponible Esperant el senyal… - No es pot canviar el format d\'horaris d\'obertura + No es pot canviar el format d\'horaris d\'obertura. prioritza distancia Aplicació de navegació OsmAnd Accediu a diferents tipus de mapa (anomenats de tessel·les o de bits), des de les tessel·les predefinides d\'OSM (com Mapnik) a imatges de satèl·lit i capes específiques com mapes meteorològics, climàtics, geològics, de relleu, etc. @@ -793,7 +776,7 @@ Objectiu El filtre \'%1$s\' s\'ha eliminat Les dades dels PDI s\'han actualitzat (se n\'han carregat {0}) - No s\'han pogut carregar dades del servidor + No s\'han pogut carregar dades del servidor. Acostar el zoom us permet actualitzar els PDIs Voleu actualitzar les dades locals des d\'Internet? Edificis: {0}, {1}, {2} @@ -814,7 +797,7 @@ Voleu eliminar aquest filtre\? Sense ruta Àudio de trucada telefònica (interrupció de la música Bluetooth del cotxe) - "Habiliteu el connector \"Enregistrament de ruta\" per utilitzar els serveis de registre d\'ubicació (enregistrament GPX, seguiment en directe)" + Habiliteu el connector \"Enregistrament de ruta\" per utilitzar els serveis de registre d\'ubicació (enregistrament GPX, seguiment en directe) Habiliteu el GPS a les preferències L\'aplicació ZXing Barcode Scanner no està instal·lada. La voleu cercar a Google Play? Esquema de color de carreteres @@ -875,7 +858,7 @@ peces Línies de nivell Corbes de nivell - "Carreteres " + Carreteres Mapes estàndards No mostris els límits administratius regionals (nivells 5 a 9). Límit de velocitat @@ -918,7 +901,7 @@ Espera màxima per corregir Dades d\'àudio/vídeo Esteu segur què voleu aturar la navegació? - "N\'esteu segur que voleu eliminar la vostra destinació (i les vostres fites)?" + N\'esteu segur que voleu eliminar la vostra destinació (i les vostres fites)\? Mostra Fotografia %1$s %2$s Fes una fotografia @@ -1091,9 +1074,9 @@ Info depuració FPS Ordre optimitzat de les fites de la ruta fins a la destinació. Creació d\'itineraris prement el mapa o utilitzant o modificant fitxers GPX existents, per planificar un trajecte i mesurar la distància entre punts. El resultat es pot desar com un fitxer GPX que podreu usar més endavant com una referència. - "Des de la versió 4.4 d\'Android (KitKat) no podeu baixar i actualitzar els mapes en l\'antiga carpeta (%s). Voleu copiar tots els fitxers de l\'OsmAnd a la nova destinació? -\n Nota 1: Els vostres fitxers obsolets quedaran intactes (els podeu esborrar manualment). -\n Nota 2: En el nou lloc d\'emmagatzemament no serà possible compartir fitxers entre l\'OsmAnd i l\'OsmAnd+." + Des de la versió 4.4 d\'Android (KitKat) no podeu baixar i actualitzar els mapes en l\'antiga carpeta (%s). Voleu copiar tots els fitxers de l\'OsmAnd a la nova destinació\? +\n Nota 1: Els vostres fitxers obsolets quedaran intactes (els podeu esborrar manualment). +\n Nota 2: En el nou lloc d\'emmagatzemament no serà possible compartir fitxers entre l\'OsmAnd i l\'OsmAnd+. S\'està copiant el fitxer (%s) a la nova destinació… S\'estan copiant els fitxers de dades de l\'OsmAnd a la nova destinació (%s)… S\'estan copiant fitxers de dades de l\'OsmAnd… @@ -1304,7 +1287,7 @@ Als darrers metres Edificis amb colors codificats per tipus Mida d\'imatge de la càmera - Estableix la mida de la imatge de la càmera. + Estableix la mida de la imatge de la càmera Mapa esquemàtic Cotxe Bicicleta @@ -1319,7 +1302,6 @@ Tot Aquest connector activa la funcionalitat d\'enregistrar i desar els vostres trajectes, sigui prement sobre el mapa el giny de gravació GPX, o sigui desant-los tots en un fitxer GPX automàticament. \n -\n \nLes rutes enregistrades es poden compartir amb els vostres amics o aportar-les per ser utilitzades a OSM. Els atletes poden utilitzar els seus registres per monitoritzar els seus entrenaments. Es pot fer una anàlisi bàsica de les rutes directament a OsmAnd com la durada de cada volta, velocitat mitjana, etc., i, per descomptat, es poden analitzar amb eines especialitzades de tercers. Enregistrament de trajectes h @@ -1373,7 +1355,7 @@ Amaga Activa la pantalla Activa la pantalla del dispositiu (si no ho està) en aproximar-se a un gir. - "%1$s necessita aquest permís per la funcionalitat de posar la pantalla en mode d\'estalvi d\'energia." + %1$s necessita aquest permís per la funcionalitat de posar la pantalla en mode d\'estalvi d\'energia. Mai Inici Cerca per @@ -1521,10 +1503,10 @@ No utilitzeu Adreça Aquest connector completa el mapa OsmAnd i la seva navegació en produir mapes nàutics per cabotatge, regates i altres tipus de esports d\'aigua. - -Un complement de mapa específic per OsmAnd us proporcionarà tot tipus de senyals nàutiques i símbols gràfics, per navegació interior o propera a la costa. La descripció de cada senyal de navegació us donarà els detalls que calguin per identificar-les i del seu significat (categoria, forma, color, seqüència, referència, etc.). - -Per retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aquest connector o canviar a com es desitgi <<Estil del Mapa>> dins <<Configuració del Mapa>>. +\n +\nUn complement de mapa específic per OsmAnd us proporcionarà tot tipus de senyals nàutiques i símbols gràfics, per navegació interior o propera a la costa. La descripció de cada senyal de navegació us donarà els detalls que calguin per identificar-les i del seu significat (categoria, forma, color, seqüència, referència, etc.). +\n +\nPer retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aquest connector o canviar a com es desitgi <<Estil del Mapa>> dins <<Configuració del Mapa>>. Aquest connector per l\'OsmAnd us proporciona els detalls de les pistes d\'esquí en baixada, de travessa i alpí així com de telefèrics i remuntadors a tot el món. Les rutes i pistes es mostren amb el codi de colors que els correspon segons la seva dificultat i amb un estil de mapa especial «Hivern» que s\'associa a un paisatge nevat. \n \nEn activar aquests canvis de visualització l\'estil del mapa canvia a «Hivern i esquí», i es mostren totes les característiques del paisatge a l\'hivern. Aquesta vista es pot revertir tant en activar-la altra cop com en canviar-la a «Estil del mapa» dins «Configuració del mapa». @@ -1712,7 +1694,7 @@ Per retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aqu Utilitzeu un nom de categoria que encara no existeixi. Nom de categoria Afegeix una nova categoria - "El mapa restringit a carreteres no cal, donat que ja teniu el mapa estàndard (complet). Que baixi igualment?" + El mapa restringit a carreteres no cal, donat que ja teniu el mapa estàndard (complet). Que baixi igualment\? %1$.1f de %2$.1f MB %.1f MB Actualitzeu tot (%1$s MB) @@ -1729,7 +1711,7 @@ Per retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aqu El mapa de %1$s està a punt per ser utilitzat. Mostra el mapa El mapa base mundial (d\'abast mundial i poc detall) no es troba o està caducat. Considereu baixar-lo per una tenir una perspectiva global. - Si es desactiva s\'engega amb la pantalla del mapa. + «Desactivat» inicia el mapa directament. Indiqueu el nom del país Pujada S\'ha creat un PDI a OSM @@ -1929,11 +1911,10 @@ Per retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aqu Marcadors actius Marcadors de mapa Marcador de mapa - El nom de fitxer inclou un caràcter il·legal + Caràcter il·legal en el nom del fitxer Afegiu els marcadors de mapa amb el mapa Aquesta subscripció permet actualitzacions horàries de tots els mapes del món. \nPart dels ingressos es retornen a la comunitat OSM en retribuir cada contribució OSM. -\n \nSi aprecieu OsmAnd i OSM i els voleu recolzar mentre l\'utilitzeu, aquesta és la via perfecta per fer-ho. Pugeu la vostra nota OSM anònimament o utilitzant el vostre perfil OpenStreetMap.org. Afegeix un lapse de temps @@ -2020,7 +2001,7 @@ Per retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aqu És necessari per baixar mapes. Cercant la localització… Espai lliure - "Magatzem de dades d\'OsmAnd (per mapes, fitxers GPX, etc.): %1$s." + Magatzem de dades d\'OsmAnd (per mapes, traces, etc.): %1$s. Autoritza Permet accedir a la localització Troba la meva localització @@ -2180,11 +2161,11 @@ Per retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aqu S\'ha canviat el mapa de fons a \"%s\". Codi de localització obert OLC no vàlid - +\n
OLC curt -Proporcioneu el codi complet - OLC complet vàlid -Abasta l\'àrea: %1$s x %2$s +\nProporcioneu el codi complet
+ OLC complet vàlid +\nRepresenta l\'àrea: %1$s x %2$s Un botó per paginar la llista que segueix. Divisió automàtica de les gravacions un cop aturades Comença un nou segment desprès de 6 min d\'interrupció, una traça nova si es superen les 2 hores o un nou fitxer si encara dura més i ha canviat la data. @@ -2241,7 +2222,7 @@ Abasta l\'àrea: %1$s x %2$s
\n Gaudiu del guiatge visual i de veu, representant PDIs (punts d\'interès), creant i gestionat traces GPX, activant la representació de corbes de nivell i d\'informació d\'elevació (requereix connector), optant entre els modes de conducció amb vehicle, bicicleta o com vianant, editant d\'OSM i molt més.
Recupera les compres Tipus de lletra - Navegació GPS + Navegació GPS \n• Trieu el mode desconnectat (no hi hauran càrrecs de roaming si sou a l\'estranger) o el mode en línia (més àgil) \n• El guiatge de veu gir-a-gir us dirigeix pel camí (veus enregistrades i sintètiques) \n• La ruta es tornarà a calcular si us desvieu de la proposta anterior @@ -2251,7 +2232,8 @@ Abasta l\'àrea: %1$s x %2$s \n• L\'escala del mapa s\'ajusta a la vostra velocitat \n• Cerca de destinacions per adreça, tipus (p. ex.: Aparcament, restaurant, hotel, gasolinera, museu), o per les coordenades geogràfiques \n• Gestiona punts de pas en el vostre itinerari -\n• Enregistreu la vostra o baixeu una traça GPX i seguiu-la +\n• Enregistreu la vostra o baixeu una traça GPX i seguiu-la +\n
Esquí \nEl connector de mapes d\'esquí d\'OsmAnd us permet veure les pistes segons la seva dificultat i d\'altres informacions addicionals, com ara la ubicació dels ascensors i altres equipaments. Ciclisme @@ -2265,11 +2247,13 @@ Abasta l\'àrea: %1$s x %2$s \n• La Viquipèdia, en el vostre idioma preferit, us pot ajudar molt visitant una ciutat \n• Parades de transport públic (autobús, tramvia, tren), incloent-hi noms de línia, suport per la navegació en una ciutat nova \n• La navegació GPS en mode vianant genera la vostra ruta per on pugueu passar -\n•Baixeu i seguiu una traça GPX o enregistreu i compartiu la vostra
- "Col·laboreu amb Openstreetmap (OSM) +\n• Baixeu i seguiu una traça GPX o enregistreu i compartiu la vostra +\n + Col·laboreu amb Openstreetmap (OSM) \n• Informant de dades errònies \n• Pujant traces GPX a OSM directament des de l\'aplicació -\n• Afegint PDIs i penjar-los a OSM directament (o més tard si no esteu connectats)" +\n• Afegint PDIs i penjar-los a OSM directament (o més tard si no esteu connectats) +\n Analitza en el mapa Visible OsmAnd es de codi obert i s\'està desenvolupant activament. Tothom pot contribuir a l\'aplicació informant d\'errors, millorant traduccions o aportant codi de noves característiques. A més, el projecte es recolza en contribucions econòmiques per finançar la programació i les proves de noves funcionalitats. @@ -2329,14 +2313,16 @@ Abasta l\'àrea: %1$s x %2$s \n• Compartiu la vostra ubicació perquè els vostres amics us puguin trobar \n• Conserveu els vostres llocs més importants a \'Preferits\' \n• Us permet escollir com es mostrar els noms al mapa: en anglès, la lengua local o amb ortografia fonètica -\n• Mostra representacions especialitzades disponibles a la xarxa, imatges de satèl·lit (Bing), diferents superposicions com traces GPX d\'exploració/navegació i capes addicionals amb un grau transparència variable +\n• Mostra representacions especialitzades disponibles a la xarxa, imatges de satèl·lit (Bing), diferents superposicions com traces GPX d\'exploració/navegació i capes addicionals amb un grau transparència variable +\n Navegació \n• Funciona en línia (ràpid) o sense connexió (sense càrrecs de roaming quan sigueu a l\'estranger) \n• Indicacions de veu a cada gir (amb missatges gravats i sintetitzats) \n• Orientació opcional del carril, visualització del nom de la via i el temps estimat d\'arribada \n• Admet punts de pas intermedis \n• Revisió automàtica de la ruta quan us aparteu de la ruta proposada -\n• Cerca de llocs per adreça, tipus (per exemple: restaurant, hotel, gasolinera, museu) o coordenades geogràfiques +\n• Cerca de llocs per adreça, tipus (per exemple: restaurant, hotel, gasolinera, museu) o coordenades geogràfiques +\n OsmAnd + (OSM Automated Navigation Directions) és una aplicació per consulta de mapes i de navegació, amb accés a les dades obertes d\'OSM, d\'abast mundial i gran qualitat. \nFruïu la navegació amb indicacions visuals i de veu, mostrant PDIs (punts d\'interès), creant i gestionant traces GPX, disposant de corbes de nivell i cotes puntuals, seleccioneu la navegació per vehicle, bicicleta o com a vianant, editeu OSM i molt més. \n @@ -2367,24 +2353,25 @@ Abasta l\'àrea: %1$s x %2$s \n• Mapes vectorials compactes en local que s\'actualitzen un cop al mes, com a mínim \n \n• Opció entre dades completes d\'una regió o només la xarxa viària (Exemple: tot el Japó ocupa 700 MB però només 200 MB per a la xarxa viària) - "Característiques de seguretat + Característiques de seguretat \n• Canvi automàtic entre el mode diürn/nocturn (opcional) \n• Indicacions del límit de velocitat i notificació d\'excés (opcional) -\n• Escala en funció de la velocitat (opcional) -\n• Si compartiu la vostra ubicació, els vostres amics us podran trobar" +\n• Escala en funció de la velocitat (opcional) +\n• Si compartiu la vostra ubicació, els vostres amics us podran trobar +\n Característiques per ciclistes i vianants \n• Visualització de vies per vianants, senderisme i carrils bici, ideal per activitats a l\'aire lliure \n• Representació i navegació a mida per ciclistes i vianants \n• Indicació opcional de les parades del transport públic (autobús, tramvia, tren), incloent-hi noms de línia \n• Enregistrament opcional del trajecte en un fitxer GPX local o a un servei a la xarxa \n• Indicació opcional de la velocitat i l\'altitud • Visualització de corbes de nivell i ombrejat de relleu (requereix connector) - "Col·laboreu directament a OSM + Col·laboreu directament a OSM \n• Notifiqueu errors en les dades \n• Pugeu traces GPX directament a OSM des de l\'aplicació \n• Afegiu PDIs i pugeu-los OSM (o feu-ho més tard si no esteu connectats) -\n• Enregistrament opcional del trajecte, també en segon pla (mentre el dispositiu està bloquejat) +\n• Enregistrament opcional del trajecte, també en segon pla (mentre el dispositiu està bloquejat) \nOsmAnd és un programari de codi obert que es desenvolupa activament. Tothom pot recolzar l\'aplicació informant d\'errors, millorant traduccions o programant noves característiques. El projecte també es fonamenta en les aportacions econòmiques per patrocinar la programació i validació de noves funcionalitats. -\n" +\n Visió general Anima la pròpia posició Activa el desplaçament animat del mapa de \'La meva posició\' durant la navegació. @@ -2587,7 +2574,7 @@ Abasta l\'àrea: %1$s x %2$s Mostra una línia de direcció entre la vostra ubicació i les dels marcadors actius. Mostra una o dues fletxes indicant la direcció dels marcadors actius. Seleccioneu com indicar la distància als marcadors actius. - Indiqueu el nombre d\'indicadors de direcció: + Indiqueu el nombre d\'indicadors de direcció. Més Cercant traces amb fites Crea o modifica objectes OSM @@ -2646,14 +2633,14 @@ Abasta l\'àrea: %1$s x %2$s Copia nom d\'ubicació/PDI Ubicació sense nom Mostra notes amagades - Mostra/amaga notes OSM en el mapa. + Mostra o amaga notes OSM en el mapa. GPX - adient per exportar-lo a JOSM o a altres editors d\'OSM. OSC - adient per exportar-lo a OSM. Arxiu GPX Arxiu OSC Seleccioneu el tipus de fitxer Exportació com notes d\'OSM, PDIs o les dues coses. - "Totes les dades" + Totes les dades Notes OSM Túnel encarat Túnels @@ -2677,7 +2664,7 @@ Abasta l\'àrea: %1$s x %2$s O S N - "Nom opcional del punt " + Nom opcional del punt Rutes properes a dins A dins Introduïu el nom del fitxer. @@ -2755,7 +2742,7 @@ Abasta l\'àrea: %1$s x %2$s Viquipèdia sense connexió Mapes amb corbes de nivell i ombrejat de relleu Desbloca totes les funcions de OsmAnd - "Viquiviatges " + Viquiviatges Articles de Viquiviatges d\'arreu Obre l\'enllaç en línia de Viquipèdia L\'enllaç s\'obrirà en el vostre navegador. @@ -2865,7 +2852,7 @@ Abasta l\'àrea: %1$s x %2$s Subscripcions Només mostra imatges de 360º Arrenca - "Esteu utilitzant el mapa {0} mitjançant OsmAnd. Voleu iniciar la versió sencera d\'OsmAnd \?" + Esteu utilitzant el mapa {0} mitjançant OsmAnd. Voleu iniciar la versió sencera d\'OsmAnd \? Voleu iniciar OsmAnd\? Guaraní Un botó per canviar entre els modes diürn i nocturn d\'OsmAnd. @@ -3088,7 +3075,7 @@ Abasta l\'àrea: %1$s x %2$s Navegació de tercers Seleccioneu els perfils que voleu que es mostrin a l\'aplicació. Perfils d\'aplicació - Esquí alpí/descens + Esquí alpí i de descens Servei de baixades d\'OsmAnd Magenta Icona @@ -3157,7 +3144,7 @@ Abasta l\'àrea: %1$s x %2$s Utilitza el sensor de proximitat Bicicleta de muntanya, ciclomotor, cavall BRouter (fora de línia) - Esquí nòrdic o de fons + Esquí nòrdic i de fons Pistes per a esquí nòrdic o de fons. Permet les rutes avançades Rutes difícils, amb obstacles perillosos i seccions amb pendents fortes. @@ -3207,8 +3194,8 @@ Abasta l\'àrea: %1$s x %2$s Per defecte Occità Camioneta descoberta - "Ruta: distància %s, durada %s -\nCàlcul: %.1f s, %d vies, %d tessel·les)" + Ruta: distància %s, durada %s +\nCàlcul: %.1f s, %d vies, %d tessel·les) Dia Dies Dies @@ -3375,7 +3362,7 @@ Abasta l\'àrea: %1$s x %2$s Bescanvia %1$s i %2$s Punt d\'inici La traça s\'ha desat - No hi ha nom de fitxer + Nom de fitxer buit Reverteix Voleu netejar %1$s\? Diàlegs i notificacions @@ -3567,7 +3554,7 @@ Abasta l\'àrea: %1$s x %2$s Un botó per mostrar o amagar la capa de terreny al mapa. Mostra el terreny Amaga el terreny - Mostra/amaga el relleu + Mostra o amaga el relleu Ombrejat del relleu Llegenda Nivells de zoom @@ -3741,11 +3728,11 @@ Abasta l\'àrea: %1$s x %2$s Compres OsmAnd Perfils de navegació Amaga el transport públic - Mostra/amaga el transport públic + Mostra o amaga el transport públic Botó que mostra o oculta el transport públic al mapa. - Crea / Edita PDI + Crea o edita PDI Posicions d’aparcament - Afegeix / Edita Preferits + Afegeix o edita preferit Restableix la ordenació dels elements predeterminats Torna a l\'edició A cada instrucció de navegació s\'activarà la pantalla. @@ -3809,7 +3796,7 @@ Abasta l\'àrea: %1$s x %2$s Nom del fitxer REC Aturarà l\'enregistrament de traces quan es mati l\'aplicació (mitjançant aplicacions recents). (La indicació de fons OsmAnd desapareix de la barra de notificacions d\'Android.) - Trieu l\'interval d\'enregistrament general dels desplaçaments (s\'activa mitjançant el giny de gravació del mapa). + Trieu l\'interval d\'enregistrament general dels desplaçaments (s\'activa mitjançant el giny del mapa \'Enregistrament de ruta\'). Traça simplificada Només es desarà la línia del trajecte, les fites s\'esborraran. %s arxius de traces seleccionats @@ -3835,7 +3822,7 @@ Abasta l\'àrea: %1$s x %2$s Botó d\'activació • S\'ha actualitzat la funció Planifica una ruta: permet utilitzar diferents tipus de navegació per segments i afegir traces \n -\n • Nou menú Aspecte per les traces: seleccioneu color, gruix, representació de les fletxes de direcció, icones inici/fi +\n • Nou menú Aspecte per les traces: seleccioneu color, gruix, representació de les fletxes de direcció, icones d\'inici i final \n \n • S\'ha millorat la visibilitat dels nodes ciclistes. \n @@ -3858,7 +3845,7 @@ Abasta l\'àrea: %1$s x %2$s Desenvolupament %1$s — %2$s Canvieu el càlcul de rutes de Transport Public a Java (segur) - Icones d\'Inici/Final + Icones d\'inici i final Gràcies per comprar \'Corbes de nivell\' Evita els camins per a vianants Evita els camins per a vianants @@ -3868,7 +3855,7 @@ Abasta l\'àrea: %1$s x %2$s 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 + Sessió tancada El fitxer ja s\'ha importat a OsmAnd Mapes locals Especial @@ -3881,4 +3868,5 @@ Abasta l\'àrea: %1$s x %2$s Discontinu Proporcioneu la llargada del vostre vehicle, pot haver-hi rutes restringides als vehicles llargs. No s\'ha generat correctament l\'arxiu GPX. Indiqueu-ho a l\'equip de suport per continuar investigant. + Enregistra automàticament la traça durant la navegació \ No newline at end of file diff --git a/OsmAnd/res/values-cs/phrases.xml b/OsmAnd/res/values-cs/phrases.xml index b0e0e22791..590ca94ca9 100644 --- a/OsmAnd/res/values-cs/phrases.xml +++ b/OsmAnd/res/values-cs/phrases.xml @@ -3850,4 +3850,10 @@ Střešní Bod GPX Radarová věž + Ambasáda + Služby občanům + Imigrační víza + Neimigrační víza + Konzulát + Ambasáda \ No newline at end of file diff --git a/OsmAnd/res/values-cs/strings.xml b/OsmAnd/res/values-cs/strings.xml index 374d0b113a..4c4069ba02 100644 --- a/OsmAnd/res/values-cs/strings.xml +++ b/OsmAnd/res/values-cs/strings.xml @@ -1521,7 +1521,7 @@ Délka %2$s Výškové omezení Zadejte výšku vozidla, která musí být povolena na cestách. Inteligentní přepočítávání trasy - Pro dlouhé cesty přepočítat pouze počáteční úsek trasy. + Přepočítá pouze počáteční úsek trasy. Může se hodit pro dlouhé trasy. Odhlásit Importovat do OsmAnd Přečíst celý článek (on-line) @@ -2005,7 +2005,7 @@ Délka %2$s Neomezené stahování map, aktualizací a modul Wikipedie. Míle/metry Hornolužická srbština - Nemáte zatím žádné GPX soubory + Nemáte zatím žádné soubory stop Do složky můžete také přidat GPX soubory Přidat další… Vzhled @@ -2055,10 +2055,10 @@ Délka %2$s Nahrát POI Starší vyhledávání Zobrazit starší způsob vyhledávání - Povolit dálnice - Povolit jízdu po dálnicích. + Použít dálnice + Povolí jízdu po dálnicích. Články Wikipedie v okolí - Hledat město nebo oblast + Město nebo oblast Přidat starší hledání do úvodního panelu. Srbsky (latinka) Čínsky (Hong Kong) @@ -2168,7 +2168,7 @@ Zobrazená oblast: %1$s x %2$s Zohlednit převýšení terénu (data od SRTM, ASTER a EU-DEM). Styl jízdy Vyberte složku pro soubor GPX - Soubor nemůže být přesunut. + Soubor se nepodařilo přesunout. Přesunout Trasy Doba pohybu @@ -2181,7 +2181,7 @@ Zobrazená oblast: %1$s x %2$s Průměrná rychlost Přidat nový adresář Bod(y) smazán(y). - Chystáte se smazat body (%1$d). Určitě smazat? + Opravdu chcete smazat %1$d bodů\? Potřebné obraty na trase Trasové body, body zájmu, pojmenované objekty Trasa @@ -2201,34 +2201,34 @@ Zobrazená oblast: %1$s x %2$s Možnosti parkování Děkujeme vám za zakoupení placené verze OsmAnd. Zvolte kolísání výšky - Jízda po pravé straně + Pravostranný provoz Automaticky Obnovit nákupy Mapová písma Zadejte adresu - Zadejte město + Zadejte město/oblast Zadejte směrovací číslo Nejbližší města Zvolte město - Zvolte směrovací číslo + Hledání PSČ Automatické přiblížení mapy - Klepnutím na toto tlačítko zapnete/vypnete automatické přibližování mapy v závislosti na vaší rychlosti. - Zapnout automatické přiblížení mapy - Vypnout automatické přiblížení mapy - Přidat cíl + Tlačítko pro zapnutí nebo vypnutí automatického přibližování mapy podle rychlosti. + Zapnout automatické přibližování + Vypnout automatické přibližování + Zadat cíl Nahradit cíl Přidat první mezicíl Zobrazit OSM poznámky Skrýt OSM poznámky - Klepnutím na toto tlačítko zobrazíte nebo skryjete OpenStreetMap poznámky na mapě. + Tlačítko pro zobrazení nebo skrytí OpenStreetMap poznámek na mapě. Seřazeno podle vzdálenosti - Najít Oblíbené - Pro zobrazení vrstevnic a stínování kopců je potřeba stáhnout překryvnou mapu této oblasti. - Pro zobrazení vrstevnic a stínování kopců je třeba zakoupit a aktivovat modul \"Vrstevnice\" + Hledat v Oblíbených + Pro zobrazení vertikálního stínování si stáhněte překryvnou mapu stínovaných svahů. + Pro zobrazení výškových stupňů si nainstalujte modul \'Vrstevnice\'. Skrýt od úrovně přiblížení Stáhnout mapu vrstevnic tohoto regionu. Modul - Chcete-li na mapě vidět vrstevnice, musíte koupit a nainstalovat modul \'Vrstevnice\' + Pro zobrazení výškových stupňů si zakupte a nainstalujte modul \'Vrstevnice\'. Barevné schéma Zobrazit od úrovně přiblížení Povolit soukromý přístup @@ -2237,14 +2237,14 @@ Zobrazená oblast: %1$s x %2$s Název skupiny Změnit barvu Upravit název - Animovat moji polohu - Povolit animaci mapy \'Mé polohy\' při navigaci. + Animovat vlastní polohu + Zapnout animovaný posun \'Mé polohy\' na mapě během navigace. Přehled Vyberte ulici v %1$s - Stisk tohoto tlačítka přidá střed obrazovky jako nový cíl navádění, z dříve nastaveného cíle se stane poslední mezicíl. - Stisk tohoto tlačítka přidá střed obrazovky jako nový cíl navádění. Pokud byl dříve nastaven jiný cíl, bude nahrazen. - Stisk tohoto tlačítka přidá střed obrazovky jako první mezicíl. + Tlačítko pro nastavení středu obrazovky jako nového cíle trasy. Z dříve nastaveného cíle se stane poslední mezicíl. + Tlačítko pro nastavení středu obrazovky jako nového cíle. Pokud byl dříve nastaven jiný cíl, bude nahrazen. + Tlačítko pro nastavení středu obrazovky jako prvního mezicíle. Bez překryvné vrstvy Bez podkladové vrstvy Chyba @@ -2267,19 +2267,19 @@ Zobrazená oblast: %1$s x %2$s Zvětšit okruh hledání Nic nalezeno Změňte vyhledávací dotaz nebo zvětšete okruh hledání. - Přepnout zobrazení poznámek OSM + Zobrazit nebo skrýt OSM poznámky Oprávnění - OsmAnd nemůže naimportovat soubor. Prosím zkontrolujte, zda má oprávnění číst soubor z tohoto umístění. + Nepodařilo se naimportovat soubor. Prosím zkontrolujte, zda má OsmAnd oprávnění ke čtení souboru. Vzdálenost opravená Obrázek Mapillary Otevřít Mapillary Instalovat Zlepšit pokrytí fotografií s Mapillary - Nainstalujte Mapillary a přidejte jednu nebo více fotografií na toto místo v mapě. + Nainstalujte Mapillary a přidejte fotografie na toto místo v mapě. On-line fotografie Přidat fotografie - Nemáme fotografie pro toto umístění. - Přispějte vlastním pohledem na toto místo přes Mapillary z úrovně ulice. + Zde nejsou žádné fotografie. + Sdílejte svůj vlastní pohled z úrovně ulice přes Mapillary. Umožňuje rychle přispět do Mapillary. On-line fotografie z ulic pro každého. Objevte místa, spolupracujte, zachyťte svět. Fotografie z ulic pro každého. Objevte místa, spolupracujte, zachyťte svět. @@ -2307,10 +2307,10 @@ Zobrazená oblast: %1$s x %2$s Max/Min Min/Max Pozastavit/pokračovat v navigaci - Stiskněte toto tlačítko na pozastavení, nebo pokračování navigace. + Tlačítko pro pozastavení nebo pokračování navigace. Zobrazit zprávu \"Navigace ukončena\" Spustit/ukončit navigaci - Stiskněte toto tlačítko pro spuštění, nebo zastavení navigace. + Tlačítko pro spuštění nebo zastavení navigace. Průhledná růžová Prosím přidejte alespoň jeden bod. Název souboru GPX: @@ -2348,7 +2348,7 @@ Zobrazená oblast: %1$s x %2$s Indikace vzdálenosti Seřadit podle Bez animací - Zakáže animace v aplikaci. + Vypne animace mapy. Stále zobrazovat na mapě Ukončit bez uložení? Práh pro změnu orientace mapy @@ -2365,7 +2365,7 @@ Zobrazená oblast: %1$s x %2$s Posledních 7 dní Tento rok Použít umístění - Přidat svou polohu jako startovní bod do plánu ideální trasy. + Přidejte svou polohu jako počáteční bod do plánu ideální trasy. Moje poloha Dokončit Naplánovat trasu @@ -2377,24 +2377,24 @@ Zobrazená oblast: %1$s x %2$s Zobrazit vodicí čáry Zobrazit šipky na mapě Odebrat z mapových značek - sestupně - vzestupně - Datum přidání + Z-A + A-Z + Přidáno Seřadit podle: Značky Formát souřadnic Použít systémovou klávesnici - Zvolte formát souřadnicového vstupu. Můžete ho kdykoli změnit klepnutím na \'Možnosti\'. + Zvolte formát zadávání souřadnic. Můžete ho kdykoliv změnit klepnutím na \'Nastavení. Rychlé zadávání souřadnic - Vyhnout brodům a ledovým cestám - Povede trasu mimo brody a ledové cesty. + Žádné ledové cesty a brody + Vyhne se ledovým cestám a brodům. Zobrazit prošlé Skrýt prošlé - Vyberte, jak ukazovat vzdálenost a směr k mapovým značkám na obrazovce mapy: - Nepodařilo se změnit poznámku + Zvolte, jak se bude zobrazovat vzdálenost a směr k mapovým značkám na mapě: + Nepodařilo se změnit poznámku. Upravit poznámku Upravit poznámku OSM - Přidat počáteční bod také jako cíl pro vytvoření okruhu. + Přidat kopii počátečního bodu jako cíl. Vytvořit okružní trasu Může být importováno jako Oblíbené nebo jako GPX soubor. Importovat jako soubor GPX @@ -2431,7 +2431,7 @@ Zobrazená oblast: %1$s x %2$s Zobrazit vodicí čáry od vaší polohy k aktivním značkám. Zobrazit jednu nebo dvě šipky označující směr k aktivním značkám. Zvolte způsob zobrazení vzdálenosti k aktivním značkám. - Zvolte, kolik ukazatelů směru se má zobrazit. + Zadejte počet ukazatelů směru. Počet desetinných míst Vpravo Vlevo @@ -2442,19 +2442,19 @@ Zobrazená oblast: %1$s x %2$s Klepnutí na mapu přepne ovládací tlačítka a nástroje. Režim celé obrazovky Označit prošlé - Vytvořit nebo upravit OSM POI, otevřít nebo okomentovat OSM poznámky a přispět zaznamenanými GPX soubory. + Vytvořit nebo upravit body zájmu OSM, otevřít nebo okomentovat OSM poznámky a přispět zaznamenanými GPX soubory. Odstraněné Upravené Přidané Značka %s aktivována. Klepněte na značku na mapě pro její přesunutí na první místo v aktivních značkách bez otevření kontextové nabídky. Dělejte si poznámky! - Přidejte audio, video nebo fotografickou poznámku pro každý bod na mapě, pomocí nástroje nebo kontextového menu. - Poznámky podle datumu + Přidejte audio, video nebo fotografické poznámky pro libovolný bod na mapě, pomocí nástroje nebo kontextového menu. + Multimediální poznámky podle data Podle datumu Podle typu Klepnutím nebo přidržením označte \'Místa\', pak klepněte na tlačítko značky s vlajkou. - Upravit vyhledávací dotaz. + Změňte vyhledávací dotaz. Funkce \"Jedním stiskem\" je aktivní Popisky bodů Bez názvu @@ -2482,13 +2482,13 @@ Zobrazená oblast: %1$s x %2$s Počet úprav %1$s, součet %2$s mBTC Laosky Zobrazit zavřené poznámky - Zobrazit/Skrýt OpenStreetMap poznámky na mapě. + Zobrazit nebo skrýt OpenStreetMap poznámky na mapě. GPX - vhodné pro export do JOSM nebo jiných editorů OSM. - OSC - vhodné pro export do OpenStreetMap. + OSC - vhodné pro export do OSM. Soubor GPX Soubor OSC Zvolte typ souboru - Vyberte typ exportu: OSM poznámky, POI nebo obojí. + Exportujte jako OSM poznámky, body zájmu, nebo obojí. Všechny údaje OSM poznámky Zadejte název souboru. @@ -2524,8 +2524,8 @@ Zobrazená oblast: %1$s x %2$s Volitelný název bodu Nejbližší trasy v okruhu V okruhu - Vzdálenost: nejvzdálenější jako první - Vzdálenost: nejbližší jako první + Nejvzdálenější jako první + Nejbližší jako první Divoká voda GPS navigace \n• Vyberte si mezi offline režimem (bez roamingových poplatků v zahraničí) a online režimem (rychlejší) @@ -2658,7 +2658,7 @@ Zobrazená oblast: %1$s x %2$s Odemknout všechny funkce OsmAnd Vyberte si předplatné Chcete-li dostávat offline články o cestování, je třeba koupit jednu z následujících položek: - Vyberte vhodnou položku: + Vyberte vhodnou položku Nedělat Dělat Pouze na WiFi @@ -2675,7 +2675,7 @@ Zobrazená oblast: %1$s x %2$s Cestovní průvodce Wikivoyage Článek odstraněn - Vyhledávání: stát, město, kraj + Hledejte stát, město nebo kraj Číst Články v záložkách Prozkoumat @@ -2693,8 +2693,8 @@ Zobrazená oblast: %1$s x %2$s Stáhnout soubor Začít s úpravami Získejte neomezený přístup - Aktualizace map: každý měsíc - Aktualizace map: každou hodinu + Aktualizace map každý měsíc + Aktualizace map každou hodinu Stáhnout články Wikipedie pro %1$s a číst je v režimu offline. Stahování dat z Wikipedie Otevřít článek online @@ -2718,9 +2718,9 @@ Zobrazená oblast: %1$s x %2$s Upravit akce Získejte OsmAnd Live pro odemknutí všech funkcí: Denní aktulizace mapových podkladů s neomezeným počtem stahování, všechny placené moduly, propojení s Wikipedia, Wikivoyage a mnoho dalšího. Děkujeme za Vaši zpětnou vazbu - Na Váš dotaz nebylo nic nalezeno. - Žádný výsledek vyhledávání? -\nDejte nám o tom vědět, ať to můžeme zlepšit + Bod nebo cesta nebyly nalezeny. + Žádný výsledek vyhledávání\? +\nPoskytněte nám zpětnou vazbu • Navigace: Opravený indikátor průběhu, přidána možnost pro rychlé prohození začátku a konce trasy \n \n • Mapové značky: Opravena možnost zapnutí/vypnutí skupin, nově možnost skrýt značky na mapě @@ -2737,8 +2737,9 @@ Zobrazená oblast: %1$s x %2$s \n Odesílání cesty… Zvětšit okruh hledání na %1$s - Bude odeslán váš dotaz pro vyhledávání: \"%1$s\" a také vaše poloha. \n - \n Nedochází k žádnému shromažďování osobních údajů. Zaslaná data slouží pouze k vylepšení vyhledávacího algoritmu. + Váš vyhledávací dotaz a poloha budou odeslány na: \"%1$s\". +\n +\n Nedochází k žádnému shromažďování osobních údajů. Zaslaná data slouží pouze k vylepšení vyhledávacího algoritmu. Odeslat data? Celý svět Bod %1$s byl smazán @@ -2748,7 +2749,7 @@ Zobrazená oblast: %1$s x %2$s Bylo přidáno %1$s bodů. Zadejte název a klepněte na \"Uložit\". Upravený základní styl pro zvýšení kontrastu pěších a cyklistických cest. Používá starší barvy Mapnik. Záložka - Vhodný pro off-road terénní jízdu. Vhodný pro použití se zelenými satelitními snímky použitými jako podkladová vrstva. Zmenšená tloušťka hlavních cest a naopak zvětšená tloušťka polních cest, pěšin, cyklotras a dalších cest. Založeno na \"Topo\" stylu. + Pro off-road terénní jízdu, založený na stylu \'Topo\' a pro použití se zelenými satelitními snímky jako podkladovou vrstvou. Zmenšená tloušťka hlavních cest, zvětšená tloušťka polních cest, pěšin, cyklotras a dalších cest. Otevřít odkaz Wikipedia na internetu Odkaz bude otevřen v internetovém prohlížeči. Stahování Wikipedia a Wikivoyage článků pro čtení offline je dostupné pouze předplatitelům OsmAnd Live. @@ -2764,21 +2765,21 @@ Zobrazená oblast: %1$s x %2$s Čas příjezdu do mezicíle Do průjezdního bodu Klepněte na tlačítko pro vyslechnutí odpovídajícího hlasového pokynu, aby jste zjistili chybné nebo chybějící pokyny. - Plavební navigační styl. Klíčové vlastnosti: Bóje, majáky, plavební cesty, mořské cesty a značky, přístavy, námořní služby, plavební hloubka. - Zimní režim. Klíčové vlastnosti: Vykresluje sjezdovky, lyžařské vleky a další praktické objekty pro lyžaře a snowboardisty. Nedůležité objekty jsou na mapě méně výrazné. + Pro námořní navigaci. Obsahuje bóje, majáky, plavební cesty, mořské cesty a značky, přístavy, námořní služby a hloubkové vrstevnice. + Pro lyžování. Obsahuje sjezdovky, lyžařské vleky, běžkařské trasy atd. Nedůležité objekty jsou na mapě méně výrazné. Vítejte v otevřené beta verzi - Jednoduchý a kontrastní styl pro automobilovou navigaci. Příjemný na oči v nočním režimu. Klíčové vlastnosti: Vrstevnice, kontrastní oranžové silnice, druhořadé objekty jsou méně výrazné. - Kontrastní styl určený primárně pro pěší turistiku a cyklistiku v přírodě. Dobrá čitelnost při složitém venkovním osvětlením. Klíčové vlastnosti: kontrastní silnice a přírodních objekty, různé typy tras, vrstevnice s rozšířeným nastavením, více detailů při odpovídající úrovni zvětšení než ve výchozím stylu. Umožňuje rozlišit kvalitu povrchu vozovky. Nemá noční režim. - Starý styl vykreslení jako výchozí \"Mapnik\". Klíčové vlastnosti: barvy jsou podobné \"Mapnik\" stylu. - Vysoce detailní styl pro účely cestování. Obsahuje všechna nastavení z výchozího stylu a navíc zobrazuje maximum detailů, především všechny silnice, cesty a jiné způsoby cestování. Jasně rozlišuje různé typy cest, podobně jako mnohé cestovní atlasy. Vysoce kontrastní schéma pro venkovní použití, denní a noční režim. - Obecný styl. Zjednodušené vykreslování v hustě osídlených městech. Klíčové vlastnosti: vrstevnice, trasy, kvalita povrchu cest, omezení přístupu, čísla cest, značení dle SAC, objekty pro vodní sporty. + Jednoduchý styl pro automobilovou navigaci. Příjemný noční režim, vrstevnice, kontrastní oranžové silnice, druhořadé objekty jsou méně výrazné. + Pro pěší turistiku a cyklistiku v přírodě. Dobře čitelný venku. Kontrastní silnice a přírodních objekty, různé typy tras, vrstevnice s rozšířeným nastavením, více detailů. Umožňuje rozlišit kvalitu povrchu vozovky. Nemá noční režim. + Starý výchozí styl \'Mapnik\'. Barvy jsou podobné jako styl \'Mapnik\'. + Styl pro cestování s vysokým kontrastem a maximálními detaily. Obsahuje všechna nastavení ze základního stylu OsmAnd a navíc zobrazuje maximum detailů, především silnice, cesty a jiné způsoby cestování. Jasně rozlišuje různé typy cest, podobně jako cestovní atlasy. Vhodný pro použití ve dne, v noci i venku. + Obecný styl. Čisté vykreslování hustě osídlených měst. Obsahuje vrstevnice, trasy, kvalita povrchu cest, omezení přístupu, čísla cest, značení dle SAC, objekty pro vodní sporty. Stáhněte si cestovní průvodce Wikivoyage a prohlížejte články o místech po celém světě bez připojení na internet. Bezplatný cestovní průvodce, který může upravovat každý. Cestovní průvodci jsou nyní založené na Wikivoyage. Všechny jejich funkce můžete otestovat zdarma během beta testování. Poté budou zpřístupněny předplatitelům služby OsmAnd Live a uživatelům OsmAnd+. - Můžete (a měli byste) upravovat libovolný článek na Wikivoyage. Sdílejte znalosti, zkušenosti, talent a svoji pozornost + Můžete (a měli byste) upravovat libovolný článek na Wikivoyage. Sdílejte znalosti, zkušenosti, talent a svoji pozornost. Pro pokračování prosím udělte OsmAndu oprávnění pro přístup k poloze. Černá - Na této zastávce je další provoz. + Z této zastávky je možná další doprava. • Opraven pád při startu, ke kterému docházelo na některých zařízeních \n \n • Nová akce značek: zobraz značky, které již byly projety @@ -2794,7 +2795,7 @@ Zobrazená oblast: %1$s x %2$s \n• Měření vzdálenosti: tlačítko \"Měření\" přidáno do akcí v kontextovém menu \n Hledat ulici - Nejprve vyberte město + Nejprve zvolte město/oblast Obnovit Značky, přidané jako skupina oblíbených nebo GPX bodů a označené jako prošlé, zůstanou na mapě. Pokud skupina není aktivní, značky zmizí z mapy. Ponechat prošlé značky na mapě @@ -2813,8 +2814,8 @@ Zobrazená oblast: %1$s x %2$s Obnovuje se čtvrtletně Obnovuje se ročně %1$.2f %2$s - Vyberte si frekvenci plateb, která vám vyhovuje: - Část příjmů je posílána přispěvatelům OpenStreetMap. + Interval plateb: + Příspěvky pomáhají financovat tvorbu map OSM. OsmAnd Předplatné Zobrazit pouze 360° obrázky @@ -2831,9 +2832,9 @@ Zobrazená oblast: %1$s x %2$s Kapacita Šířka Výška - Přidat cíl + Zadat cíl Přidat mezicíl - Přidat počáteční bod + Zadat počáteční bod Mezicíl přestupy pěšky @@ -2845,7 +2846,7 @@ Zobrazená oblast: %1$s x %2$s Ukázat podél trasy Simulovat navigaci Vyberte soubor s trasou, kterou chcete následovat - Hlasová oznámení + Hlasové výzvy Mezicíle Příjezd v %1$s Nejdříve prosím zadejte cíl @@ -2864,12 +2865,12 @@ Zobrazená oblast: %1$s x %2$s Typy silnic Výjezd na Vyměnit - Zobrazit/skrýt GPX trasy - Klepnutím na toto tlačítko akce se zobrazí nebo skryjí vybrané GPX trasy na mapě - Skrýt GPX trasy - Zobrazit GPX trasy + Zobrazit/skrýt stopy + Tlačítko pro zobrazení nebo skrytí vybraných stop na mapě + Skrýt stopy + Zobrazit stopy %1$d přenosů - Přidat počáteční a koncový bod + Přidat počáteční a cílový bod Přidat počáteční bod Zvolit počáteční bod Nezpevněný @@ -2926,8 +2927,7 @@ Zobrazená oblast: %1$s x %2$s %s režim Vyhněte se typům dopravy… Chůze - Maximální délka názvu značky \"%s\" je 255 znaků. -\nPro pokračování zkraťte. + Zkraťte délku názvu značky \"%s\" na méně než 255 znaků. Délka hodnoty \"%s\" "• Nová obrazovka \'Pokyny\': Zobrazuje tlačítka pro cíl Domov a Práce, zkratku pro \'předchozí trasu\', seznam aktivních GPX tras a značek, historii vyhledávání \n @@ -2951,18 +2951,18 @@ Zobrazená oblast: %1$s x %2$s Miliradiány Úhlová jednotka Změní jednotku měření azimutu. - Vyhnout se tramvajím - Vyhnout se tramvajím - Vyhnout se autobusům - Vyhnout se autobusům a trolejbusům - Vyhnout se sdíleným taxi - Vyhnout se sdíleným taxi - Vyhnout se vlakům - Vyhnout se vlakům - Vyhnout se metru + Žádné tramvaje + Vyhne se tramvajím + Žádné autobusy + Vyhne se autobusům a trolejbusům + Žádná sdílená taxi + Vyhne se sdíleným taxi + Žádné vlaky + Vyhne se vlakům + Žádné metro Vyhnout se metru a lehké železniční dopravě - Vyhnout se trajektům - Vyhnout se trajektům + Žádné trajekty + Vyhne se trajektům • Zobrazování času na přestup mezi hromadnou dopravou \n \n • Upravené rozhraní detailů trasy @@ -2995,7 +2995,7 @@ Zobrazená oblast: %1$s x %2$s Určete, která data dovolíte aplikaci OsmAnd sdílet. Klepněte na „Povolit“, pokud souhlasíte s našimi %1$s Soukromí a zabezpečení - Zvolte, které údaje s námi sdílíte + Zvolte údaje ke sdílení Ne, díky Povolit Název profilu @@ -3030,12 +3030,12 @@ Zobrazená oblast: %1$s x %2$s Nejprve je třeba uložit změny profilu Odstranit profil Opravdu chcete odstranit profil „%s“ - Zvolte základní profil + Zvolte výchozí profil Vyberte typ navigace Auto, nákladní auto, motocykl Horské kolo, moped, kůň Chůze, turistika, běh - Všechny typy hromadné dopravy + Typy hromadné dopravy Loď, veslování, plachtění Letadlo, plachtění Geokódování @@ -3071,7 +3071,7 @@ Zobrazená oblast: %1$s x %2$s \n \nSvoji volbu můžete kdykoliv změnit v Nastavení > Soukromí a zabezpečení. Pomozte nám pochopit, které regiony a země jsou v mapách nejpopulárnější. - Pomozte nám pochopit, které funkce OsmAnd jsou nejpopulárnější. + Pomůže nám zjistit popularitu funkcí OsmAnd. Můžete přidat vaši vlastní upravenou verzi souboru routing.xml v ..osmand/routing Klepněte znovu pro změnu orientace mapy Min. rychlost @@ -3090,15 +3090,15 @@ Zobrazená oblast: %1$s x %2$s Terénní Nastavit profil Profil si udrží své vlastní nastavení - Vybrat výchozí nastavení mapy u profilu - Vybrat výchozí nastavení obrazovky u profilu - Vybrat výchozí nastavení navigace u profilu + Zvolte nastavení mapy pro profil + Zvolte nastavení obrazovky pro profil + Zvolte nastavení navigace pro profil Určete maximální počet přestupů Počet přestupů Probudit na odbočce - Nastavte čas, po který bude obrazovka zapnutá. + Nastavte, jak dlouho bude obrazovka zapnutá. Použít senzor přiblížení - Zamávejte rukou přes horní část obrazovky pro zapnutí obrazovky při navigování. + Zamávání rukou nad obrazovkou ji zapne. 1. třída 2. třída 3. třída @@ -3110,7 +3110,7 @@ Zobrazená oblast: %1$s x %2$s Obecná klávesnice WunderLINQ Parrot - Prosíme, zapněte alespoň jeden profil aplikace, pro použití tohoto nastavení. + Pro použití tohoto nastavení zapněte prosím alespoň jeden profil aplikace. Zimní cesta Ledová cesta Zimní a ledové cesty @@ -3159,7 +3159,7 @@ Zobrazená oblast: %1$s x %2$s Nainstalované moduly Nastavení navigace Vzhled aplikace, jednotky, oblast - Upozornění jsou zobrazena vlevo dole během navigace. + Upozornění zobrazená vlevo dole během navigace. Jazyk a výstup Obnovit do základního nastavení Spravovat profily aplikace… @@ -3170,14 +3170,14 @@ Zobrazená oblast: %1$s x %2$s Mapa během navigace Mapa během navigace Další - Hmotnost, výška, rychlost + Hmotnost, výška, délka, rychlost Parametry vozidla Hlasová oznámení se přehrávají pouze během navigace. Navigační pokyny a oznámení Hlasová oznámení Konfigurace parametrů trasy Parametry trasy - Použito pro odhadnutí času příjezdu u cest s neznámým povrchem a pro omezení rychlosti u všech cest (může ovlivnit trasu) + Odhaduje času příjezdu u cest s neznámým povrchem a omezuje rychlost na všech cestách (může ovlivnit trasu) Nastavení profilu: OsmAnd používá UTM Standard, který je podobný, ale nikoliv identický s UTM NATO formátem. Příklad @@ -3210,8 +3210,8 @@ Zobrazená oblast: %1$s x %2$s Zadejte cestu k adresáři s OsmAnd daty Změnit adresář pro OsmAnd data\? Přesunout do nového umístění - Vnitřní úložiště, skryté před uživateli a aplikacemi, přístupné výhradně pro OsmAnd - Změnit adresář úložiště dat + Vnitřní úložiště pro OsmAnd (skryté před uživateli a jinými aplikacemi). + Změnit složku pro ukládání dat Typ sjezdovky Nováček Začátečník @@ -3240,44 +3240,44 @@ Zobrazená oblast: %1$s x %2$s Opravdu chcete aktualizovat všechny mapy (%1$d)\? Sdíleno Upřednostňovat nezpevněné cesty - Upřednostňovat nezpevněné cesty. + Pro navigaci upřednostňovat nezpevněné cesty před zpevněnými. OSM úpravy Exportovat profil OsmAnd profil: %1$s - Profil „%1$s“ již existuje. Přepsat\? + \'%1$s\' již existuje. Přepsat\? Profil nelze exportovat. - Import profilu: + Importovat profil Přidejte profil otevřením jeho souboru pomocí OsmAnd. %1$s chyba importu: %2$s - Úspěšně importováno: %1$s + %1$s importován. Prohodit %1$s a %2$s Počáteční bod Trasa uložena - Název souboru je prázdný + Prázdný název souboru Vrátit zpět Vyčistit %1$s\? Dialog stahování map Dialogy a oznámení - Správa vyskakovacích upozornění, oznámení a dialogů zobrazovaných aplikací OsmAnd. + Správa vyskakovacích upozornění, dialogů a oznámení. Navrhované mapy - Tyto mapy je třeba používat s modulem + Tyto mapy jsou potřebné pro modul. Přidané profily - Nový profil přidaný do OsmAnd modulem + Profily přidané modulem Vypnout Přidán nový modul - Přidat nový profil „%1$s“\? + Přidat nový profil \'%1$s\'\? Trasy upravené pro klasické lyžování bez bruslení. Zahrnuje trasy upravené menšími sněžnými vozidly a stopy vytvořené samotnými lyžaři. Povolit pouze trasy pro bruslení na lyžích Sněžný skútr Vlastní modul pro OsmAnd - Změny aplikovány na profil %1$s. - Nelze přečíst %1$s. - Nelze zapsat %1$s. - Nelze importovat %1$s. + Změny aplikovány na profil \'%1$s\'. + Nepodařilo se přečíst z \'%1$s\'. + Nelze zapsat do \'%1$s\'. + Nelze importovat z \'%1$s\'. Stínování svahů Terén Stínované svahy používají tmavé odstíny pro vyjádření svahů, vrcholů a nížin. - Svahy jsou barevné vizualizace terénu. + Svahy využívají barvy k vizualizaci strmosti terénu. Nastavte minimální a maximální úroveň přiblížení, při které bude vrstva zobrazená. Pro zobrazení stínování kopců jsou potřeba další mapy. Pro zobrazení svahů jsou potřeba další mapy. @@ -3285,7 +3285,7 @@ Zobrazená oblast: %1$s x %2$s Průhlednost Úrovně přiblížení Legenda - Zapněte pro zobrazení stínovaných svahů. O tomto typu map se dozvíte více na našich stránkách + Zapněte pro zobrazení stínovaných svahů nebo sklonu svahů. O těchto typech map se dozvíte více na našich stránkách. Všechna data z %1$s jsou naimportovaná, můžete použít tlačítka níže k otevření části aplikace pro jejich správu. Import dokončen Položky přidány @@ -3304,7 +3304,7 @@ Zobrazená oblast: %1$s x %2$s Trasa bude přepočítaná pokud vzdálenost od trasy k aktuální poloze je větší než zvolená hodnota. %1$s z %2$s Svahy - Zobrazit/skrýt terén + Zobrazit nebo skrýt terén Skrýt terén Zobrazit terén Tlačítko pro zobrazení nebo skrytí vrstvy terénu na mapě. @@ -3316,7 +3316,7 @@ Zobrazená oblast: %1$s x %2$s Osmiúhelník Čtverec Min - Nahradit jiný bod tímto + Nahradit jiný bod tímto. Lyžařské okruhy Úhel Úhel: %s° @@ -3333,7 +3333,7 @@ Zobrazená oblast: %1$s x %2$s \nModul zůstane v zařízení i po odstranění aplikace OsmAnd. Modul vypnutý Otevřít nastavení - Vypnout přepočítávání + Žádné přepočítávání Zadejte prosím název profilu Vyberte data k importu. Některé položky již existují @@ -3359,12 +3359,12 @@ Zobrazená oblast: %1$s x %2$s Některé články Wikipedie nemusí být dostupné ve vašem jazyce. Zvolte jazyky, v nichž se články Wikipedie objeví na mapě. \nBěhem čtení článku budete moci přepínat mezi všemi dostupnými jazyky. Pro zobrazení bodů zájmu Wikipedie jsou potřeba další mapy. - Hlavní akce mohou obsahovat pouze 4 tlačítka. + Obsahuje pouze 4 tlačítka. Hlavní akce Položky můžete přesouvat pouze v rámci této kategorie. Modul pro vývojáře Položky - Zvolte jazyky, v nichž se články Wikipedie zobrazí na mapě. Při čtení článku můžete přepínat mezi všemi dostupnými jazyky. + Zvolte jazyky článků Wikipedie na mapě. Při čtení článku můžete přepínat mezi všemi dostupnými jazyky. Některé články Wikipedie nemusí být dostupné ve vašem jazyce. Kantonština Jižní min @@ -3397,9 +3397,9 @@ Zobrazená oblast: %1$s x %2$s %1$s / %2$s Platba bude stržena z vašeho účtu Google Play po potvrzení nákupu. \n -\nPředplatné se automaticky prodlužuje, pokud ho před termínem obnovení nezrušíte. Platba za předplatné (měsíc/tři měsíce/rok) bude stržena vždy jen v den obnovení. +\n Předplatné se automaticky prodlužuje, pokud ho před termínem obnovení nezrušíte. Platba za předplatné (měsíc/tři měsíce/rok) bude stržena vždy jen v den obnovení. \n -\nSvé předplatné můžete spravovat nebo zrušit v nastavení Google Play. +\n Své předplatné můžete spravovat nebo zrušit v nastavení Google Play. Hledat typy bodů zájmu Zkombinujte body zájmu různých kategorií. Klepnutím na přepínač vyberete všechny, klepnutím na levou stranu vyberete kategorie. Další mapy @@ -3447,12 +3447,12 @@ Zobrazená oblast: %1$s x %2$s Mercatorovo zobrazení Formát uložení Nastavte minimální a maximální úroveň přiblížení, při níž se zobrazí nebo načte online mapa. - Tyto parametry ovlivňují zobrazení při použití jako mapy nebo překryvu/podkladu. + Ovlivňuje zobrazení při použití jako mapy nebo překryvu/podkladu. \n -\n%1$s: Zobrazení mapy bude omezeno na vybrané úrovně přiblížení. +\n%1$s: Mapa bude omezena na vybrané úrovně přiblížení. \n -\n%2$s: Úrovně přiblížení, při nichž budou zobrazeny původní dlaždice. Mimo tyto hodnoty se dlaždice přeškálují. - Čas obnovení v minutách. Dlaždice v mezipaměti budou znovu načteny po uplynutí zadaného času. Necháte-li toto pole prázdné, dlaždice z tohoto zdroje se nebudou obnovovat nikdy. +\n%2$s jsou úrovně přiblížení, při nichž budou zobrazeny původní dlaždice. Mimo tyto hodnoty se dlaždice přeškálují. + Dlaždice v mezipaměti budou znovu načteny po uplynutí zadaného počtu minut. Necháte-li toto pole prázdné, dlaždice z tohoto zdroje se nebudou obnovovat nikdy. \n \nJeden den má 1440 minut. \nJeden týden má 10 080 minut. @@ -3465,7 +3465,7 @@ Zobrazená oblast: %1$s x %2$s Pro pokračování je potřeba nastavit pracovní dny Trasa mezi body Naplánovat trasu - Přidat k trase + Přidat ke stopě Zobrazit ikony startu a cíle Zvolte šířku Vyberte interval pro zobrazování značek na trase se vzdáleností nebo časem. @@ -3476,12 +3476,12 @@ Zobrazená oblast: %1$s x %2$s Importovat trasu Otevřít existující trasu Vytvořit novou trasu - Vyberte trasu k otevření. + Vyberte stopu k otevření. Hotovo Zadejte prosím název bodu Současný cílový bod na trase bude smazán. Jestliže to je poslední cíl, navigace se zastaví. Stáhnout Wikipedia mapy - Získejte informace o zájmových bodech z Wikipedie. Je to váš offline kapesní průvodce - zapněte Wikipedia plugin a užívejte si články o objektech okolo Vás. + Získejte informace o zájmových bodech z Wikipedie. Je to váš offline kapesní průvodce - zapněte modul Wikipedia a užívejte si články o objektech okolo vás. Přidaný bod nebude na mapě vidět, protože vybraná skupina je skrytá. Můžete jej najít v \"%s\". Enduro motorka Motorový skútr @@ -3493,7 +3493,7 @@ Zobrazená oblast: %1$s x %2$s Uložit jako soubor trasy Sledovat trasu Zvolte soubor trasy, kterou chcete sledovat - Zvolte soubor trasy, kterou chcete sledovat, nebo jej importujte ze zařízení. + Zvolte soubor stopy, kterou chcete sledovat, nebo jej importujte ze svého zařízení. Zvolit jinou trasu Navigovat z mé polohy k trase Bod trasy pro navigování @@ -3518,12 +3518,12 @@ Zobrazená oblast: %1$s x %2$s Omezení délky Azimut %1$s smazáno - Ke kompletnímu smazání dat o rychlostních radarech je nutný restart. + Restartovat aplikaci pro kompletní smazání dat o rychlostních radarech. Odinstalovat a restartovat Toto zařízení nemá rychlostní kamery. Inline brusle - Smazat následující cílový bod - Umožní ovládat úroveň přiblížení mapy pomocí tlačítek hlasitosti zařízení. + Smazat nejbližší cílový bod + Ovládat úroveň přiblížení mapy pomocí tlačítek hlasitosti zařízení. Tlačítka hlasitosti pro přibližování Mezní vzdálenost Navigační profil @@ -3576,12 +3576,12 @@ Zobrazená oblast: %1$s x %2$s Naposledy změněno Název: Z – A Název: A – Z - Ikony startu/cíle + Ikony startu a cíle Děkujeme za zakoupení modulu \'Vrstevnice\' Přihlásit se pomocí OAuth pro použití funkcí editace OSM Přihlásit pomocí OAuth Vymazat OpenStreetMap OAuth token - Odhlášení úspěšné + Byli jste odhlášeni Soubor je již importovaný v OsmAnd Použít dvoufázový algoritmus A* pro výpočet trasy Graf @@ -3692,11 +3692,11 @@ Zobrazená oblast: %1$s x %2$s Úvodní panel Skrýt veřejnou dopravu Zobrazit veřejnou dopravu - Zobrazit/skrýt veřejnou dopravu + Zobrazit nebo skrýt veřejnou dopravu Tlačítko pro zobrazení nebo skrytí veřejné dopravy na mapě. - Vytvořit / upravit bod zájmu + Vytvořit nebo upravit bod zájmu Parkovací místa - Přidat / upravit oblíbený bod + Přidat nebo upravit oblíbený bod Obnovit výchozí pořadí položek Zpět k úpravám Tlačítko akce přepne mezi zvolenými profily. @@ -3722,7 +3722,7 @@ Zobrazená oblast: %1$s x %2$s Tlačítko napájení Senzor přiblížení Zvolte časový limit vypnutí obrazovky po probuzení (\"%1$s\" znamená bez časového limitu.) - Musíte přidat aspoň dva body. + Musíte přidat aspoň dva body Spravovat předplatné S vaším předplatným je problém. Klikněte na tlačítko pro přechod do nastavení předplatného v Google Play a opravte způsob platby. Předplatné OsmAnd Live skončilo @@ -3740,7 +3740,7 @@ Zobrazená oblast: %1$s x %2$s MGRS Simulovat polohu pomocí zaznamenané stopy GPX. Co je nového - Tlačítko pro určení středu obrazovky jako výchozího bodu a výpočet trasy do cíle nebo otevření dialogu pro výběr cíle. + Tlačítko pro nastavení středu obrazovky jako výchozího bodu a výpočet trasy do cíle nebo otevření dialogu pro výběr cíle. Pro jízdu na sněžném vozidle na vyhrazených cestách. Vlastní profil založte na jednom ze základních profilů. Ten určí základní nastavení jako viditelnost nástrojů, jednotky rychlosti a vzdálenosti. Toto jsou základní profily aplikace a návrhy vlastních profilů, na které mohou být rozšířeny: Ohodnotit @@ -3893,28 +3893,28 @@ Zobrazená oblast: %1$s x %2$s Tato nastavení jsou globální a platí pro všechny profily Přihlásit se do OpenStreetMap Přihlásit se do OpenStreetMap.org - Zaregistrovat se do OpenStreetMap + Přihlásit se do OpenStreetMap Můžete zobrazit své dosud neodeslané změny či chyby v OSM v %1$s. Odeslané body se již v OsmAnd nezobrazují. - Musíte se přihlásit, abyste mohli odesílat nová nebo změněná data. + Přihlaste se, abyste mohli odesílat nová nebo změněná data, \n -\nMůžete se přihlásit pomocí bezpečné metody OAuth, nebo pomocí jména a hesla. - Použít jméno a heslo +\nbuď pomocí bezpečné metody OAuth, nebo pomocí jména a hesla. + Přihlásit se pomocí jména a hesla Účet - Přihlašovací jméno + Uživatelské jméno Historie značek - Veřejná znamená, že trasa bude veřejně dostupná ve vašich GPS trasách a veřejných seznamech GPS tras. Data poskytnutá prostřednictvím API nebudou odkazovat na vaši stránku s trasou. Časová razítka bodů trasy nebudou dostupná prostřednictvím veřejného GPS API a body nebudou chronologicky seřazeny. Ostatní uživatelé si ale stále budou moci stáhnout nezpracovanou trasu z veřejného seznamu spolu se všemi časovými razítky, které obsahuje. - Soukromá znamená, že trasa se neobjeví v žádném veřejném seznamu a body trasy budou dostupném prostřednictvím veřejného GPS API bez časových razítek, ale nebudou chronologicky seřazeny. + \"Veřejná\" znamená, že trasa je veřejně dostupná ve vašich GPS trasách, ve veřejných seznamech GPS tras a také ve veřejném seznamu stop s nezpracovanými časovými razítky. Data poskytnutá prostřednictvím API nebudou odkazovat na vaši stránku s trasou. Časová razítka bodů trasy nebudou dostupná prostřednictvím veřejného GPS API a body nebudou chronologicky seřazeny. + \"Soukromá\" znamená, že trasa se neobjeví v žádném veřejném seznamu a body trasy budou dostupné prostřednictvím veřejného GPS API bez časových razítek a nebudou chronologicky seřazeny. Odeslat soubor GPX do OpenStreetMap Zadejte značky oddělené čárkou. - Sledovatelná znamená, že trasa se neobjeví v žádném veřejném seznamu, ale body trasy budou dostupné prostřednictvím veřejného GPS API s časovými razítky. Ostatní uživatelé si budou moci stáhnout zpracované body z vaší trasy, které ale nebude možné přímo spojit s vámi. - Identifikovatelná znamená, že trasa bude veřejně dostupná ve vašich GPS trasách a veřejných seznamech GPS tras, tzn. ostatní uživatelé si budou moci stáhnout nezpracovanou trasu a propojit ji s vaším uživatelským jménem. Data poskytnutá prostřednictvím API se budou odkazovat na vaši původní stránku s trasou. Časová razítka bodů trasy budou dostupná prostřednictvím veřejného GPS API. + \"Sledovatelná\" znamená, že trasa se neobjeví v žádném veřejném seznamu, ale zpracované body trasy s časovými razítky (které nelze přímo spojit s vámi) budou dostupné prostřednictvím veřejného GPS API. + \"Identifikovatelná\" znamená, že trasa bude veřejně dostupná ve vašich GPS trasách a veřejných seznamech GPS tras, tzn. ostatní uživatelé si budou moci stáhnout nezpracovanou trasu a propojit ji s vaším uživatelským jménem. Veřejná data bodů trasy s časovými razítky poskytnutá prostřednictvím GPS API se budou odkazovat na vaši původní stránku s trasou. Zavřít OSM poznámku Komentovat OSM poznámku - Můžete se přihlásit bezpečnou metodou OAuth nebo použít své přihlašovací jméno a heslo. + Přihlaste se bezpečnou metodou OAuth nebo použijte své přihlašovací jméno a heslo. Přidat fotku Zaregistrovat na \nOpenPlaceReviews.org - Fotografie poskytuje open source projekt OpenPlaceReviews.org. Před odesláním svých fotografií se musíte zaregistrovat na webové stránce. + Přihlaste se na webových stránkách open source projektu OpenPlaceReviews.org a budete moci odesílat ještě více fotografií. Vytvořit nový účet Už mám účet %1$s: %2$s @@ -3942,4 +3942,24 @@ Zobrazená oblast: %1$s x %2$s Ve výchozím stavu vypnuto: běží-li OsmAnd na popředí, obrazovka se nevypne. \n \nJe-li zapnuto, OsmAnd vypne obrazovku podle systémového limitu. + Tyto akce jsou dostupné po stisknutí tlačítka “%1$s”. + Importovat nebo nahrát soubory stop + Zadejte interval ukládání pro obecný záznam trasy (aktivovaný přes widget Záznam trasy na mapové obrazovce). + Historie vyhledávání + Kajak + Motorový člun + Přidat do Mapillary + Přidat do OpenPlaceReviews + OsmAnd zobrazuje fotografie z několika zdrojů: +\nOpenPlaceReviews - fotografie bodů zájmu +\nMapillary - pouliční fotografie +\nWeb / Wikimedia - fotografie bodů zájmu specifikované v OpenStreetMap datech. + Zdroje + Přibližná velikost souboru + Vyberte data k exportu do souboru. + Vyžadováno pro import + Na vašem zařízení je volných pouze %1$s. Uvolněte prosím nějaké místo nebo zrušte některé položky k exportu. + Není zde dostatek místa + Vyberte skupiny, které se mají importovat. + Vyberte položky, které se mají importovat. \ No newline at end of file diff --git a/OsmAnd/res/values-da/phrases.xml b/OsmAnd/res/values-da/phrases.xml index 7f1eb79c21..a298d7653d 100644 --- a/OsmAnd/res/values-da/phrases.xml +++ b/OsmAnd/res/values-da/phrases.xml @@ -3808,7 +3808,7 @@ Stand type Ja Nej - Signal for at finde stangen + Internetadgang: kunder Kun når det er tilladt at gå Kontrast Primitiv @@ -3852,4 +3852,35 @@ Små elektriske apparater Afgangstavle Genopfyldning af drikkevand + Nej + Ja + Nej + Ja + Nej + Ja + Repræsentantkontor + Kontor + Honorærkonsul + Generalkonsulat + Konsulært agentur + Ledet af en konsul + Bopæl + Højkommissær + Delegation + Afdeling + Ledet af en ambassadør + Forbindelsesofficerer + Ambassade + Radartårn + Tagterrasse + GPX-punkt + Borgerservice + Immigrant visum + Ikke-immigrant visum + Forbindelsesofficerer + Konsulat + Ambassade + Langs gaden + Overdækket parkering + LNG \ No newline at end of file diff --git a/OsmAnd/res/values-da/strings.xml b/OsmAnd/res/values-da/strings.xml index 3943611228..d5278f0b53 100644 --- a/OsmAnd/res/values-da/strings.xml +++ b/OsmAnd/res/values-da/strings.xml @@ -385,7 +385,7 @@ Globale programindstillinger OSM-brugernavn Nødvendig for ændringer i openstreetmap.org. - OSM-kodeord + Adgangskode Baggrundstilstand OsmAnd kører i baggrunden med skærmen slukket. Format @@ -1544,7 +1544,7 @@ Højdegrænse Angiv køretøjets højde der tillades på ruter. Smart rutegenberegning - For lange ture, genberegn kun den indledende del af ruten. + Genberegner kun den oprindelige del af ruten. Kan bruges til lange ture. Log af Deaktiveret Farvelægning ifølge netværkstilhørsforhold @@ -3433,7 +3433,7 @@ Genberegning af rute Annoncere Brugernavn og adgangskode - Indstillingerne gælder for alle profiler. + Indstillinger for udvidelsen er globale, og gælder for alle profiler OSM redigering Se redigeringer eller OSM-fejl, der endnu ikke er overført i %1$s. Overførte punkter vises ikke længere. OSM @@ -3488,7 +3488,7 @@ Vinkel: %s° Vinkel Forbereder - IP typer + IP-typer Intet valgt Genveje Profiler @@ -3549,9 +3549,9 @@ Den importerede profil indeholder yderligere data. Klik på Importer for kun at importere profildata, eller vælg yderligere data, der skal importeres. Ruten vil blive genberegnet, hvis afstanden til ruten er længere end angivet parameter Mindste afstand for at genberegne ruten - OsmAnd har allerede elementer med de samme navne, som dem, der importeres. -\n -\nVælg en aktion. + OsmAnd har allerede elementer med de samme navne som de importerede. +\n +\nVælg en handling. Det angivne %1$s findes allerede. Mindste vinkel mellem placering og rute Ekstra lige segment mellem placering og den beregnede rute vises, indtil ruten genberegnes @@ -3787,7 +3787,78 @@ Kun det valgte segment genberegnes igen ved hjælp af den valgte profil. Alle efterfølgende segmenter genberegnes ved hjælp af den valgte profil. Alle tidligere segmenter genberegnes ved hjælp af den valgte profil. - Start-/slutikoner + Start- og slutikoner %1$s — %2$s Hul + Der er ikke plads nok + Længdegrænse + Tak for køb af \'Konturlinjer\' + Abonnement opkrævet pr. valgt periode. Annuller det til enhver tid på AppGallery. + Undgå gangstier + Undgå gangstier + Udvikling + OsmAnd Live-data + OsmAnd Live-data + To-faset ruteplanlægning til bilnavigation. + Log på med OAuth for at bruge osmedit-funktioner + Log ind via OAuth + Ryd OpenStreetMap OAuth-token + Logget ud + Filen er allerede importeret + Brug 2-faset A* routingalgoritme + Graf + Vent på genberegningen af ruten. +\nGrafen vil være tilgængelig efter genberegning. + Lokale kort + Særlig + Transport + Service + Symboler + Sport + Nødsituation + Rejse + Tilføj mindst to punkter + Log ind på OpenStreetMap + Log ind for OpenStreetMap.org + Log på med OpenStreetMap + Log ind for at overføre nye eller ændrede ændringer, +\n +\nenten med OAuth eller med brugernavn og adgangskode. + Log ind med brugernavn og adgangskode + Konto + Brugernavn + Administrer abonnement + OsmAnd Live-abonnementet er udløbet + OsmAnd Live-abonnement er sat på pause + OsmAnd Live-abonnement er i venteposition + Markørhistorik + Send GPX-fil til OpenStreetMap + Indtast mærker adskilt af komma. + Luk OSM-note + Kommenter OSM-note + Log ind ved hjælp af den sikre OAuth metode eller mrd brugernavn og adgangskode. + Tilføj fotos + Tilmeld på +\nOpenPlaceReviews.org + Log ind på det åbne dataprojekts webside OpenPlaceReviews.org og overfør endnu flere billeder. + Opret ny konto + Har allerede en konto + Søgehistorik + Kajak + Motorbåd + Føj til Mapillary + Føj til OpenPlaceReviews + OsmAnd viser billeder fra flere kilder: +\nOpenPlaceReviews - IP-billeder; +\nMapillary - billeder på gadeniveau; +\nWeb / Wikimedia - IP fotos angivet i OpenStreetMap data. + Ressourcer + Omtrentlig filstørrelse + Vælg de data, der skal eksporteres til filen. + Nødvendig for import + Enheden har kun %1$s fri. Frigør plads, eller fravælg nogle elementer, der skal eksporteres. + Vælg grupper, der skal importeres. + Vælg emner, der skal importeres. + Skift til dev.openstreetmap.org i stedet for openstreetmap.org for at teste overførelse af OSM-note / IP / GPX. + Brug dev.openstreetmap.org \ No newline at end of file diff --git a/OsmAnd/res/values-de/phrases.xml b/OsmAnd/res/values-de/phrases.xml index e9f39131f9..950388e493 100644 --- a/OsmAnd/res/values-de/phrases.xml +++ b/OsmAnd/res/values-de/phrases.xml @@ -3853,4 +3853,34 @@ Dachparkplätze GPX-Wegpunkt Radarturm + nein + ja + nein + ja + nein + ja + Subnationales Büro + Repräsentanzbüro + Verbindungsbüro + Honorarkonsul + Generalkonsulat + Konsularbüro + Konsularagentur + Geleitet von einem Konsul + Residenz + Nuntiatur + Mission + Interessenvertretung + Hochkommissar + Delegation + Niederlassung + Geleitet von einem Botschafter + Verbindungsbüro + Botschaft + Dienstleistungen für Bürger + Einwanderungsvisa + Nicht-Einwanderungsvisa + Verbindungsbüro + Konsulat + Botschaft \ No newline at end of file diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index a17e9b39de..6c824c4e78 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -1928,7 +1928,7 @@ Die App darf nun auf den externen Speicher schreiben, dazu ist aber ein manueller Neustart nötig. Verschieben ↑ Verschieben ↓ - Dateiname beinhaltet nicht erlaubte Zeichen + Nicht erlaubte Zeichen im Dateinamen Keine Wegpunkte gefunden Bitte Kartenmarkierungen über die Karte hinzufügen Fein @@ -2646,7 +2646,7 @@ Ort/POI-Name kopieren Unbenannter Ort Geschlossene Notizen anzeigen - OSM-Notizen auf der Karte ein-/ausblenden. + OSM-Notizen auf der Karte ein- oder ausblenden. GPX - geeignet für den Export in JOSM oder andere OSM-Editoren. OSC - geeignet für den Export nach OSM. GPX-Datei @@ -3104,13 +3104,13 @@ Extrem schwere Routen, mit gefährlichen Hindernissen und schwieriger Umgebung. Nur klassische Routen zulassen Bevorzugter Schwierigkeitsgrad - Ski Alpin/Abfahrtslauf + Ski Alpin und Abfahrtslauf Pisten für Ski Alpin oder Abfahrtslauf und Zugang zu den Skiliften. OsmAnd Download-Dienst Magenta Symbol Erfasste Daten - Skilanglauf/Nordischer Skisport + Skilanglauf und Nordischer Skisport Loipen für Skilangläufer und Nordische Skiläufer. Routen dieser Schwierigkeit bevorzugen, obwohl bei kürzerer Routenführung schwierigere oder einfachere Pisten immer noch möglich sind. Abseits der Piste @@ -3373,7 +3373,7 @@ Startpunkt Schätzt die Ankunftszeit für unbekannte Straßentypen und begrenzt die Geschwindigkeit für alle Straßen (kann die Navigation beeinflussen) Track gespeichert - Dateiname ist leer + Leerer Dateiname Zurücksetzen %1$s löschen\? Vorgeschlagene Karten @@ -3579,7 +3579,7 @@ Eine Schaltfläche zum Ein- und Ausblenden der Geländeebene auf der Karte. Gelände einblenden Gelände ausblenden - Gelände ein- / ausblenden + Gelände ein- oder ausblenden Relief Zoomstufen Transparenz @@ -3697,11 +3697,11 @@ Sie können auf diese Aktionen zugreifen, indem Sie auf die Schaltfläche \"%1$s\" tippen. Öffentliche Verkehrsmittel ausblenden Öffentliche Verkehrsmittel anzeigen - Öffentliche Verkehrsmittel anzeigen/ausblenden + Öffentliche Verkehrsmittel anzeigen oder ausblenden Schaltfläche zum Ein- oder Ausblenden der öffentlichen Verkehrsmittel auf der Karte. - POI erstellen / bearbeiten + POI erstellen oder bearbeiten Parkpositionen - Favorit hinzufügen / bearbeiten + Favorit hinzufügen oder bearbeiten Standard-Reihenfolge der Elemente wiederherstellen Zurück zur Bearbeitung Die Aktionsschaltfläche schaltet zwischen den ausgewählten Profilen um. @@ -3878,7 +3878,7 @@ Track Route Track Datei zum Folgen auswählen, oder vom Gerät importieren. Die GPX-Aufzeichnung wird angehalten, wenn OsmAnd beendet wird (über „zuletzt verwendete Apps“). (Die Hintergrunddienst-Anzeige verschwindet aus der Android-Benachrichtigungsleiste.) - Aufzeichnungsintervall für die generelle Track-Aufzeichnung festlegen (via Schaltfläche \'GPX\' auf dem Kartenbildschirm). + Aufzeichnungsintervall für die generelle Track-Aufzeichnung festlegen (wird über die Schaltfläche \'Routenaufzeichung\' auf dem Kartenbildschirm angeschaltet). Als nächstes können Sie Ihren Track mit einem Ihrer Navigationsprofile auf die nächstgelegene erlaubte Straße einrasten lassen, um diese Option zu nutzen. Track-Wegpunkt hinzufügen %s Track Dateien ausgewählt @@ -3895,7 +3895,7 @@ Wiederholen • Aktualisierte Funktion zum Planen einer Route: erlaubt die Verwendung verschiedener Navigationstypen pro Segment und die Einbeziehung von Tracks \n -\n • Neues Menü zum Erscheinungsbild von Tracks: Wählen Sie Farbe, Dicke, Richtungspfeile, Start-/Ziel-Symbole +\n • Neues Menü zum Erscheinungsbild von Tracks: Wählen Sie Farbe, Dicke, Richtungspfeile, Start- und Zielsymbole \n \n • Verbesserte Darstellung von Fahrradknotenpunkten. \n @@ -3911,7 +3911,7 @@ Zuletzt geändert Name: Z – A Name: A – Z - Start-/Ziel-Symbole + Start- und Zielsymbole Vielen Dank für den Kauf von \'Höhenlinien\' Das Abonnement wird pro ausgewähltem Zeitraum berechnet. Sie können das Abonnement jederzeit über die AppGallery kündigen. Die Bezahlung wird Ihrem AppGallery-Konto bei der Bestätigung des Kaufs belastet. @@ -3928,13 +3928,13 @@ Zwei-Phasen-Routenberechnung für die Autonavigation. Native ÖPNV Entwicklung Wechseln zu Java (sicher) Berechnung des ÖPNV-Routings - Abmeldung erfolgreich + Abgemeldet Datei wurde bereits in OsmAnd importiert Anmelden über OAuth OpenStreetMap OAuth-Token löschen Was ist neu Für das Schneemobilfahren mit speziellen Straßen und Tracks. - Durchführen eines OAuth-Logins zur Nutzung der osmedit-Funktionen + Anmelden mit OAuth zur Nutzung der osmedit-Funktionen 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 @@ -3957,29 +3957,48 @@ OsmAnd Live Abonnement ist abgelaufen OsmAnd Live Abonnement wurde ausgesetzt OsmAnd Live Abonnement liegt auf Eis - Anmeldung bei OpenStreetMap - Anmeldung bei OpenStreetMap.org + Anmeldung für OpenStreetMap + Anmeldung für OpenStreetMap.org Anmelden mit OpenStreetMap - Sie müssen sich anmelden, um Änderungen hochzuladen. + Melden Sie sich an, um Änderungen hochzuladen, \n -\nSie können sich mit der sicheren OAuth-Methode anmelden oder Ihren Benutzernamen und Ihr Passwort verwenden. - Benutzername und Passwort verwenden +\nentweder mit OAuth oder mit Ihrem Benutzernamen und Passwort. + Anmelden mit Benutzername und Passwort Konto - Login + Benutzername Historie der Marker GPX-Datei an OpenStreetMap senden Geben Sie durch Komma getrennte Tags ein. - Öffentlich bedeutet, dass der Track in Ihren GPS-Tracks und in GPS-Track Verzeichnissen öffentlich angezeigt wird. Die über die API bereitgestellten Daten verweisen nicht auf Ihre Track-Seite. Die Zeitstempel der Trackpunkte sind nicht über die öffentliche GPS-API verfügbar, und die Punkte sind nicht chronologisch geordnet. Andere Benutzer können jedoch nach wie vor den Rohtrack aus der öffentlichen Trackliste und alle darin enthaltenen Zeitstempel herunterladen. - Identifizierbar bedeutet, dass der Track in Ihren GPS-Tracks und in öffentlichen GPS-Track Verzeichnissen angezeigt wird. Andere Benutzer können den Rohtrack herunterladen und mit Ihrem Benutzernamen verknüpfen. Daten, die über die Trackpunkte-API geliefert werden, verweisen auf Ihre ursprüngliche Track-Seite. Die Zeitstempel der Trackpunkte sind über die öffentliche GPS-API verfügbar. - Privat bedeutet, dass der Track nicht in öffentlichen Verzeichnissen auftaucht. Punkte des Tracks werden weiterhin über die öffentliche GPS-API ohne Zeitstempel verfügbar sein, aber nicht chronologisch geordnet. - Verfolgbar bedeutet, dass der Track in keiner öffentlichen Auflistung auftaucht, aber Trackpunkte weiterhin über die öffentliche GPS API mit Zeitstempel verfügbar sein werden. Andere Benutzer werden nur verarbeitete Trackpunkte Ihres Tracks herunterladen können, die nicht direkt mit Ihnen in Verbindung gebracht werden können. + \"Öffentlich\" bedeutet, dass der Track öffentlich in Ihren GPS-Tracks und in öffentlichen GPS-Track Verzeichnissen mit Zeitstempeln in Rohform angezeigt wird. Die über die API bereitgestellten Daten verweisen nicht auf Ihre Track-Seite. Die Zeitstempel der Trackpunkte sind nicht über die öffentliche GPS API verfügbar, und die Trackpunkte sind nicht chronologisch geordnet. + \"Identifizierbar\" bedeutet, dass der Track in Ihren GPS-Tracks und in öffentlichen GPS-Track Verzeichnissen angezeigt wird, d.h. andere Benutzer können den Track herunterladen und mit Ihrem Benutzernamen verknüpfen. Öffentliche, mit Zeitstempel versehene Trackpunkt-Daten von der GPS API, die über die Trackpunkt API bereitgestellt werden, verweisen auf Ihre ursprüngliche Trackseite. + \"Privat\" bedeutet, dass der Track nicht in öffentlichen Verzeichnissen auftaucht, aber seine Trackpunkte in nicht chronologischer Reihenfolge über die öffentliche GPS API ohne Zeitstempel verfügbar sind. + \"Verfolgbar\" bedeutet, dass die Spur nicht in öffentlichen Auflistungen auftaucht, aber verarbeitete Trackpunkte mit Zeitstempeln davon (die nicht direkt mit Ihnen in Verbindung gebracht werden können) durch Downloads von der öffentlichen GPS API. OSM Notiz schließen OSM Notiz kommentieren - Sie können sich mit der sicheren OAuth-Methode anmelden oder Ihren Benutzernamen und Passwort verwenden. + Melden Sie sich mit der sicheren OAuth-Methode an oder verwenden Sie Ihren Benutzernamen und Ihr Passwort. Foto hinzufügen Registrieren bei \nOpenPlaceReviews.org - Fotos werden vom offenen Datenprojekt OpenPlaceReviews.org zur Verfügung gestellt. Um Ihre Fotos hochladen zu können, müssen Sie sich auf der Website anmelden. + Melden Sie sich auf der Open Data Website OpenPlaceReviews.org an, um noch mehr Fotos hochzuladen. Neues Konto erstellen Ich habe bereits ein Konto + Suchverlauf + Kajak + Motorboot + Zu Mapillary hinzufügen + Zu OpenPlaceReviews hinzufügen + OsmAnd zeigt Fotos aus verschiedenen Quellen: +\nOpenPlaceReviews - POI Fotos; +\nMapillary - Bilder auf Straßenebene; +\nWeb / Wikimedia - POI Fotos, die in OpenStreetMap Daten angegeben sind. + Quellen + Ungefähre Dateigröße + Wählen Sie die Daten aus, die in die Datei exportiert werden sollen. + Benötigt für Import + Ihr Gerät hat nur %1$s Speicherplatz frei. Bitte machen Sie etwas Platz frei oder heben Sie die Auswahl einiger zu exportierender Objekte auf. + Es gibt nicht genug Speicherplatz + Wählen Sie Gruppen aus, die importiert werden sollen. + Wählen Sie Elemente aus, die importiert werden sollen. + Wechseln Sie zu dev.openstreetmap.org anstelle von openstreetmap.org, um das Hochladen von OSM-Hinweisen / POI / GPX zu testen. + dev.openstreetmap.org verwenden \ No newline at end of file diff --git a/OsmAnd/res/values-el/strings.xml b/OsmAnd/res/values-el/strings.xml index 9ef59f2e76..780a4d0fef 100644 --- a/OsmAnd/res/values-el/strings.xml +++ b/OsmAnd/res/values-el/strings.xml @@ -3264,7 +3264,7 @@ Οι φωνητικές ανακοινώσεις να γίνονται μόνο κατά την πλοήγηση. Οδηγίες πλοήγησης και ανακοινώσεις Φωνητικές ανακοινώσεις - Οπτικές προειδοποιήσεις + Προειδοποιήσεις οθόνης Ρύθμιση παραμέτρων διαδρομής Παράμετροι διαδρομής Εκτιμά τον χρόνο άφιξης αγνώστων τύπων δρόμων και περιορίζει την ταχύτητα σε όλους τους δρόμους (μπορεί να επηρεάσει τη διαδρομή) diff --git a/OsmAnd/res/values-eo/phrases.xml b/OsmAnd/res/values-eo/phrases.xml index 99dda63d74..fb0ab54dc6 100644 --- a/OsmAnd/res/values-eo/phrases.xml +++ b/OsmAnd/res/values-eo/phrases.xml @@ -3843,4 +3843,34 @@ tegmento GPX-punkto Radar-turo + oficejo + honora konsulo + ĝenerala konsulejo + konsula oficejo + konsula agentejo + gvidata de konsulo + rezidejo + nunciejo + misio + sekcio de interesoj + alta komisario + delegitaro + branĉo + gvidata de ambasadestro + kvazaŭ-ambasadejo + ambaadejo + Servoj por ŝtatanoj + Vizoj enmigraj + Vizoj neenmigraj + Kvazaŭ‑ambasadejo + Konsulejo + Ambasadejo + ne + jes + ne + jes + ne + jes + subŝtata/provinca oficejo + reprezenta oficejo \ No newline at end of file diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index ea11a3cdb0..d6716c22f0 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -415,7 +415,7 @@ Uzantnomo kaj pasvorto al OSM Datum-konservada dosierujo Filtri laŭ nomo - Entajpu ion por serĉi + Enigu ion por serĉi A-GPS informoj Etikedoj “riparu min!” Administri @@ -749,9 +749,9 @@ Korekto de altitudo Tutmondaj maraj navigadpunktoj Elektu kategorion - Entajpu nomon - Entajpu kategorion - Entajpu priskribon. + Enigu nomon + Enigu kategorion + Enigu priskribon. Norma koloro Magneta direkto Relativa direkto @@ -1596,7 +1596,7 @@ Elekti manieron de bildigado de vektora mapo Montri retpaĝon de interesejo Montri telefonon de interesejo - entajpu tekston por filtri + enigu tekston por filtri Alta ekrandistingivo Ne etendi (kaj malklarigi) map‑kahelojn ĉe alt‑distingivaj ekranoj. Serĉi transporton publikan @@ -1651,7 +1651,7 @@ Ne povas ŝargi GPX. Sendi raporton Ne povas trovi iujn elŝutitajn mapojn en la SD-karto. - Entajpu serĉatan interesejon + Enigu serĉatan interesejon Ia Dankon al Yandex pro informoj pri trafiko. Yandex - informoj pri trafiko @@ -1805,7 +1805,7 @@ GGG:MM:SS.S Adreso Krei interesejon - Entajpu nomon de ŝatata ejo + Enigu nomon de ŝatata ejo Ŝatataj Aldonis ŝatatan punkton “{0}”. Aldoni al ŝatataj @@ -1905,7 +1905,7 @@ Senpagaj elŝutoj uzitaj Montras nombron da pluaj senpagaj elŝutoj. Bonvolu elekti kie vi volas konservi mapoj kaj aliaj datum-dosieroj. - Entajpu nomon de lando + Enigu nomon de lando Nova versio Unuaj paŝoj kun OsmAnd Ebloj @@ -1947,7 +1947,7 @@ Nombro da kontribuintoj Nombro da redaktoj Raportoj por - Dosiernomo enhavas malpermesitan signon + Malpermesata signo en dosiernomo {0} elemento(j) elektita(j) Koordinat-formo Formo de geografiaj koordinatoj. @@ -2038,7 +2038,7 @@ Subkategorioj Transliterumi nomojn Transliterumi, se nomo en %1$s mankas - Entajpu urbon, adreson aŭ nomon de interesejo + Enigu urbon, adreson aŭ nomon de interesejo Bronzkolora hela Bronzkolora malhela Kolor-skemo de nivelkurboj @@ -2366,12 +2366,12 @@ Aktivigi aŭtomatan map-skaladon Malaktivigi aŭtomatan map-skaladon Paŭzigita - Entajpu urbon aŭ lokon - Entajpu poŝtkodon + Enigu urbon aŭ lokon + Enigu poŝtkodon Proksimaj urboj Elekti urbon Serĉi poŝtkodon - Entajpu adreson + Enigu adreson Elekti straton en %1$s Sumigo @@ -2415,7 +2415,7 @@ Neniuj fotoj tie ĉi. Instali Pliigi fotan atingon de Mapillary - Instalu Mapillary por aldoni fotojn al tiu ĉi loko sur la mapo. + Instalu la aplikaĵon Mapillary por aldoni fotojn al tiu ĉi loko sur la mapo. Malfermi Mapillary Mapillary-foto Korektita distanco @@ -2430,7 +2430,7 @@ de Montri bildojn aldonitajn nur Dato - Entajpu uzantnomon + Enigu uzantnomon Montri nur bildojn aldonitajn de Uzantnomo Filtri bildojn laŭ alŝutinto, laŭ dato aŭ laŭ tipo; aktivaj nur je pligrandigo. @@ -2456,7 +2456,7 @@ Reprovi Esploru mapon kaj aldonu punktojn Bonvolu aldoni almenaŭ unu punkton. - GPX-dosiera nomo: + Dosiernomo de GPX: Montri sur mapo post konservi Aldoni navigadpunkton Konservi GPX‑navigadpunkton @@ -2541,7 +2541,7 @@ Vi devas aldoni almenaŭ unu markon por uzi tiun ĉi eblon. Malĝusta formo Malĝusta enigo - Entajpu novan nomon + Enigu novan nomon Reen Montri Aldonis intercelojn al mapmarkoj @@ -2634,7 +2634,7 @@ Kopii nomon de punkto Sennoma ejo Montri fermitajn rimarkojn - Montri/kaŝi OSM‑rimarkojn sur la mapo. + Montri aŭ kaŝi OSM‑rimarkojn sur la mapo. GPX - taŭga por elporti al JOSM aŭ aliaj OSM-redaktiloj. OSC - taŭga por elporti al OSM. GPX-dosiero @@ -2652,8 +2652,8 @@ Agordi kiel komencpunkton Eraro dum enporti mapon Enportis mapon - Entajpu dosiernomon. - Entajpu longitudon + Enigu dosiernomon. + Enigu longitudon Entajpu latitudon Entajpu latitudon kaj longitudon GG°MM′SS″ @@ -2772,7 +2772,7 @@ Redakti punkton Aldoni punkton Konservi kiel spuron - Vi aldonis %1$s punktojn. Entajpu dosiernomon kaj frapetu “konservi”. + Vi aldonis %1$s punktojn. Enigu dosiernomon kaj frapetu “konservi”. Forigis la punkton %1$s Mondo Ni sendos vian serĉ-peton: “%1$s” kun via pozicio. @@ -3050,7 +3050,7 @@ Ĉefa profilo Elektu specon de navigado Bonvolu elekti specon de navigo por la nova aplikaĵa profilo - Entajpu nomon por profilo + Enigu nomon por profilo Unue devas enigi nomon por profilo. Nomo neebla Jam ekzistas profilo kun la sama nomo @@ -3080,9 +3080,9 @@ Rulumu supren/malsupren por ŝanĝi pligrandigon de mapo. Eskap-klavo revenas al al aplikaĵo WunderLINQ App. Stiri per WunderLINQ Aldonu almenaŭ unu elementon al la listo en agordoj de “rapida ago” - Skiado alpa/malsuprenira + Skiado alpa kaj malsuprenira Skivojoj por skiado alpa (malsuprenira) kaj vojetoj al skitelferoj. - Skiado nordia/skikurada + Skiado nordia kaj skikurada Skivojoj por skiado nordia (skikurada). Skiado ekskursa Skivojoj ekskursaj. @@ -3261,7 +3261,7 @@ Elŝutu la detalan mapon %s, por vidi tiun ĉi areon. Ĉu movi datum‑dosierojn OsmAnd al la nova loko\? \n%1$s → %2$s - Entajpu dosier‑indikon + Enigu dosierindikon Dosierujo… Algluu dosier‑indikon por dosierujo de OsmAnd‑datumoj Ĉu ŝanĝi datum‑dosierujon OsmAnd\? @@ -3362,7 +3362,7 @@ Anstataŭigi komencpunkton per celo Simuli vian pozicion uzante registritan GPX‑kurson. Konservis kurson - Dosiernomo estas malplena + Malplena dosiernomo Malfari Butono por agordi la ekranan centron kiel komencpunkton. Sekve vi estos petita por agordi finpunkton aŭ ekos kalkulado de kurso. Montri reton de nodoj de biciklaj kursoj @@ -3572,7 +3572,7 @@ Mapklarigo Nivelombrumo %1$s el %2$s - Montri/kaŝi teren‑formon + Montri aŭ kaŝi teren‑formon Kaŝi teren‑formon Montri teren‑formon Butono por montri/kaŝi tavolon de formo de tereno sur la mapo. @@ -3690,10 +3690,10 @@ Vi povas ekigi tiujn agojn per frapeti la butonon “%1$s”. Kaŝi publikan transporton Montri publikan transporton - Montri/kaŝi publikan transporton + Montri aŭ kaŝi publikan transporton Butono por montri/kaŝi publikan transporton sur la mapo. - Krei/redakti interesejon - Aldoni/forigi ŝatatan ejojn + Krei aŭ redakti interesejon + Aldoni aŭ forigi ŝatatan ejojn Pozicioj de parkumado Restarigi implicitan ordigon de elementoj Reen al redaktado @@ -3876,7 +3876,7 @@ Refari • plibonigoj al “plani kurson”: eblo uzi diversajn specojn de navigo por ĉiu segmento aparte kaj ampleksi spurojn \n -\n• nova menuo de aspekto por spuroj: eblo elekti koloron kaj dikecon, montri sagetojn de direkto kaj vidigi markojn de komenco/fino de la spuro +\n• nova menuo de aspekto por spuroj: eblo elekti koloron kaj dikecon, montri sagetojn de direkto kaj vidigi markojn de komenco kaj fino de la spuro \n \n• plibonigita videblo de biciklaj nodoj \n @@ -3890,7 +3890,7 @@ \n \n Registri - Elektu la intervalon de registrado por la ĝenerala registrado de spuro (aktivigata per la fenestraĵo “registri spuron” sur la mapo). + Elektu la intervalon de registrado por la ĝenerala registrado de spuro (aktivigebla per la fenestraĵo “registri spuron” sur la mapo). Simpligita spuro Nur la linio de kurso estos konservita, la navigadpunktoj estos forigitaj. Dosiernomo @@ -3909,7 +3909,7 @@ \n La abono aŭtomate renoviĝos escepte se ĝi estos nuligita antaŭ la dato de renoviĝo. La pago estos prenita por la renoviĝa periodo (monato/tri monatoj/jaro) nur je la dato de renoviĝo. \n \n Vi povas administri kaj rezigni viajn abonojn per la agordoj de AppGallery. - Emblemoj komenco/fino + Emblemoj de komenco kaj fino Dankon al vi por aĉeti la kromprogramon “nivelkurboj” Abonpago prenita por la elektita periodo. VI ĉiam povas rezigni abonon ĉe AppGallery. Eviti irejojn @@ -3921,10 +3921,10 @@ Du-faza difinado de kurso por aŭtomobila navigo. Indiĝena metodo de publik-transporta navigo Aktivigi (sekuran) metodon por kalkuli kursojn de publika transporto uzante programlingvon Java - Ensaluti uzante OAuth por redakti la mapon OSM + Ensaluti per OAuth por redakti la mapon OSM Ensaluti per OAuth Forigi ĵetonon OpenStreetMap OAuth - Sukcese elsalutinta + Elsalutinta Por veturi per motorsledo sur dediĉitaj vojoj. Dosiero jam estas enportita al OsmAnd Uzi 2-fazan A* algoritmon de navigo @@ -3955,26 +3955,45 @@ Ensaluti al OpenStreetMap Ensaluti al OpenStreetMap.org Ensaluti per OpenStreetMap - Vi devas ensaluti por alŝuti novajn aŭ modifitajn ŝanĝojn. + Ensalutu por alŝuti novajn aŭ modifitajn ŝanĝojn \n -\nVi povas ensaluti per la sekura metodo OAuth aŭ per enigi uzantnomon kaj pasvorton. - Uzi uzantnomon kaj pasvorton +\naŭ per la sekura metodo OAuth aŭ per enigi uzantnomon kaj pasvorton. + Ensaluti per uzantnomo kaj pasvorto Konto Uzantnomo Historio de markoj Sendi GPX‑dosieron al OpenStreetMap Enigu etikedojn disigitajn per komo (,). - “Publika” signifas, ke la GPX‑spuro estos publika videbla en “miaj spuroj” kaj en la publika listo de spuro (GPS‑spuroj). Datumoj liverataj per la API ne ligos al paĝo de via spuro. Tempindikoj de punktoj ne estos akireblaj per la publika API GPS, kaj la punktoj ne estos ordigitaj laŭtempe. Tamen aliaj uzantoj plue povos elŝuti la nepritraktitan spuron el la publika listo de spuroj kune kun ĉiuj ampleksitaj tempindikoj. - “Privata” signifas, ke la GPX‑spuro montriĝos en neniu publika listo, sed ĝiaj punktoj plue estos akireblaj per la publika API GPS sen tempindikoj, sed tiuj punktoj estos ordigitaj laŭtempe. - “Identigebla” signifas, ke la GPX‑spuro estos publike videbla en “miaj spuroj” kaj en la publika listo de spuroj (GPS‑spuroj), aliaj uzantoj povos elŝuti vian nepritraktitan spuron kaj ligi ĝin al via uzantnomo. Datumoj liveritaj per la API de spuroj ligos al originala paĝo de via spuro. Tempindikoj de la spuro estos akireblaj per la publika API GPS. - “Spurebla” signifas, ke la GPX‑spuro ne estos montrata en publikaj listoj, sed punktoj el ĝi plue estos akireblaj per la publika API GPS kune kun tempindikoj. Aliaj uzantoj povos elŝuti nur pritraktitajn punktojn el via spuro, kiuj ne povos esti senpere ligitaj al vi. + “Publika” signifas, ke la GPX‑spuro estos publike videbla en “miaj spuroj” kaj en la publika listo de spuroj (GPS‑spuroj) kun tempindikoj kaj en nepritraktita formo. Datumoj liverataj per la API ne ligos al paĝo de via spuro. Tempindikoj de spurpunkto ne estos akireblaj per la publika API GPS, kaj spurpunktoj ne estos laŭtempe ordigitaj. + “Privata” signifas, ke la GPX‑spuro montriĝos en neniu publika listo, sed ĝiaj punktoj neordigitaj laŭtempe estos akireblaj per la publika API GPS sen tempindikoj. + “Identigebla” signifas, ke la GPX‑spuro estos publike videbla en “miaj spuroj” kaj en la publika listo de spuroj (GPS‑spuroj), aliaj uzantoj povos elŝuti vian nepritraktitan spuron kaj ligi ĝin al via uzantnomo. Publikaj datumoj kun tempindikoj el la API GPS akireblaj per la API de spur‑punktoj indikos al originala paĝo de via spuro. + “Spurebla” signifas, ke la GPX‑spuro ne montriĝos en publikaj listoj, sed pritraktitaj punktoj kun tempindikoj el ĝi (kiuj ne povos esti senpere ligitaj al vi) estos elŝuteblaj per la publika API GPS. Fermi OSM-rimarkon Komenti OSM-rimarkon - Vi povas ensaluti per l sekura metodo OAuth aŭ per uzi uzantnomon kaj pasvorton. + Ensalutii per la sekura metodo OAuth aŭ per uzi uzantnomon kaj pasvorton. Aldoni foton Registri ĉe \nOpenPlaceReviews.org - Fotoj estas liverataj de la malferm‑datuma projekto OpenPlaceReviews.org. Por alŝuti viajn fotojn, vi devas registri ĉe la retejo. + Ensaluti en la paĝon de la malferm‑datuma projekto OpenPlaceReviews.org por alŝuti fotojn. Krei novan konton Mi jam havas konton + Serĉi en historio + Kajako + Motorboato + OsmAnd montras fotojn el diversaj fontoj: +\nOpenPlaceReviews – fotoj de interesejoj; +\nMapillary – strat‑nivela fotaro; +\ninterreto, Vikimedio – fotoj de interesejoj difinitaj en OpenStreetMap-datumoj. + Rimedoj + Proksimuma dosiergrando + Elektu datumojn por elporti al dosiero. + Necesa por enporti + En via aparato estas nur %1$s da libera spaco. Liberigu iom da spaco aŭ malelektu iujn elementojn de elporto. + Mankas spaco + Aldoni al Mapillary + Aldoni al OpenPlaceReviews + Elektu grupojn por enporti. + Elektu elementojn por enporti. + Baskuli al dev.openstreetmap.org anstataŭ openstreetmap.org por testi alŝuti OSM‑rimarkojn, interesejojn, GPX‑spurojn. + Uzi dev.openstreetmap.org \ No newline at end of file diff --git a/OsmAnd/res/values-es-rAR/phrases.xml b/OsmAnd/res/values-es-rAR/phrases.xml index c72ea55517..30855ccc5b 100644 --- a/OsmAnd/res/values-es-rAR/phrases.xml +++ b/OsmAnd/res/values-es-rAR/phrases.xml @@ -400,7 +400,7 @@ Buceo Submarinismo Canódromo - Equitación + Deportes ecuestres Hockey sobre césped Golf Gimnasia @@ -1234,7 +1234,7 @@ Paso a nivel peatonal;Cruce peatonal ferroviario Paso a nivel;Cruce ferroviario Observatorio de aves - Equitación + Centro ecuestre Jardín Césped Pastizal @@ -3857,4 +3857,34 @@ Azotea Punto GPX Torre de radar + No + + No + + No + + Subnacional + Oficina representativa + Oficina + Cónsul honorario + Consulado general + Oficina consular + Agencia consular + Dirigido por un cónsul + Residencia + Nunciatura + Misión + Sección de intereses + Alto comisionado + Delegación + Sucursal;Ramal + Dirigido por un embajador + Enlace + Embajada + Servicios al ciudadano + Visas de inmigrante + Visas de no inmigrante + Enlace + Consulado + Embajada \ No newline at end of file diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index 3d4b451190..e92749d57b 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -1528,7 +1528,7 @@ Enfoque hiperfocal Profundidad de campo extendido (EDOF) Enfoque al infinito - Modo de enfoque macro (primer plano) + Enfoque macro (primer plano) Enfoque continuo Reproducir sonido al fotografiar Define el sonido o silencio al fotografiar. @@ -3458,7 +3458,7 @@ Velocidad mínima Precisión mínima Desplazamiento mínimo - Restablecer ajustes del complemento a valores predefinidos + Restablecer complemento a valores predefinidos División de grabación Usar la aplicación del sistema Reproducir sonido al fotografiar @@ -3927,7 +3927,7 @@ Desarrollo nativo del transporte público Cambiar al cálculo de ruta Java (seguro) del transporte público Novedades - Inicia sesión con OAuth para usar las funciones de edición de OSM + Ingresar con OAuth para usar las funciones de edición de OSM Ingresar a través de OAuth Vaciar llave OAuth de OpenStreetMap Sesión finalizada @@ -3958,13 +3958,13 @@ La suscripción a OsmAnd Live se ha pausado La suscripción a OsmAnd Live está en espera Iniciar sesión en OpenStreetMap - Ingresar a OpenStreetMap.org - Debes iniciar sesión para subir cambios nuevos o modificados. + Ingresar en OpenStreetMap.org + Debes iniciar sesión para subir los cambios nuevos o modificados. \n -\nPuedes ingresar usando el método seguro de OAuth o usar el nombre de usuario y contraseña. - Usar nombre de usuario y contraseña +\nPuedes ingresar usando el método seguro de OAuth o con nombre de usuario y contraseña. + Ingresar con usuario y contraseña Cuenta - Iniciar sesión + Ingresar Ingresar con OpenStreetMap Historial de marcadores Enviar archivo GPX a OpenStreetMap @@ -3985,4 +3985,23 @@ Historial de búsqueda Kayak Lancha a motor + Recursos + Tamaño aproximado del archivo + Marca los datos que serán exportados al archivo. + Necesario para importar + El dispositivo sólo tiene %1$s libre. Por favor, libera algo de espacio o desmarca algunos elementos a exportar. + Sin espacio suficiente + Añadir a Mapillary + Añadir a OpenPlaceReviews + OsmAnd muestra fotos de varios repositorios: +\nOpenPlaceReviews (fotos de PDI); +\nMapillary (imágenes a nivel de calle); +\nWeb / Wikimedia (fotos de PDI incluidas en los datos de OpenStreetMap). + Separador + Marca los grupos que serán importados. + Marca los elementos que serán importados. + Cambia a la versión para desarrolladores «dev.openstreetmap.org» en lugar de openstreetmap.org para probar la carga de PDI, notas de OSM y archivos GPX. + Usar dev.openstreetmap.org + No se puede subir la imagen, inténtalo más tarde + Elegir imagen \ No newline at end of file diff --git a/OsmAnd/res/values-es-rUS/phrases.xml b/OsmAnd/res/values-es-rUS/phrases.xml index 5f62bd195b..9980bdccd7 100644 --- a/OsmAnd/res/values-es-rUS/phrases.xml +++ b/OsmAnd/res/values-es-rUS/phrases.xml @@ -400,7 +400,7 @@ Buceo Submarinismo Canódromo - Equitación + Deportes ecuestres Hockey sobre césped Golf Gimnasia @@ -1234,7 +1234,7 @@ Paso a nivel peatonal;Cruce peatonal ferroviario Paso a nivel;Cruce ferroviario Observatorio de aves - Equitación + Centro ecuestre Jardín Césped Pastizal @@ -3857,4 +3857,34 @@ Azotea Apartadero Punto GPX + Subnacional + Oficina representativa + Oficina + Enlace + Dirigido por un embajador + Residencia + Nunciatura + Misión + Sección de intereses + Alto comisionado + Embajada + Delegación + Sucursal;Ramal + + No + Visas de no inmigrante + + No + Visas de inmigrante + + No + Servicios al ciudadano + Enlace + Embajada + Dirigido por un cónsul + Cónsul honorario + Consulado + Consulado general + Oficina consular + Agencia consular \ No newline at end of file diff --git a/OsmAnd/res/values-es-rUS/strings.xml b/OsmAnd/res/values-es-rUS/strings.xml index dedb0d0009..6e8220cde8 100644 --- a/OsmAnd/res/values-es-rUS/strings.xml +++ b/OsmAnd/res/values-es-rUS/strings.xml @@ -1528,7 +1528,7 @@ Enfoque hiperfocal Profundidad de campo extendido (EDOF) Enfoque al infinito - Modo de enfoque macro (primer plano) + Enfoque macro (primer plano) Enfoque continuo Reproducir sonido al fotografiar Define el sonido o silencio al fotografiar. @@ -1921,7 +1921,7 @@ Informe completo Nombre de usuario y contraseña de OSM Informe - El nombre del archivo contiene caracteres ilegales + Carácter ilegal en el nombre del archivo Añade marcadores a través del mapa No se encontraron puntos de referencia Fino @@ -2462,7 +2462,7 @@ Navega por el mapa y añade puntos Medir distancia Añadir al menos un punto. - Nombre del GPX: + Nombre del archivo GPX: Mostrar en el mapa al guardar Añadir punto de referencia Guardar punto GPX @@ -3085,9 +3085,9 @@ Cambia el zoom del mapa desplazando la rueda hacia arriba y abajo. La tecla «Escape» retrocede a la aplicación WunderLINQ. Controlar con WunderLINQ Añadir al menos un elemento a la lista en los ajustes de «Acción rápida» - Esquí alpino o de descenso + Esquí alpino y de descenso Pistas de esquí alpino o de descenso y acceso a remontes mecánicos. - Esquí de travesía o nórdico + Esquí de travesía y nórdico Senderos para esquí nórdico o de travesía. Esquí de travesía Rutas para esquí de travesía. @@ -3368,7 +3368,7 @@ Estima el tiempo de llegada para los tipos de caminos desconocidos, y limita la velocidad para todos los caminos (puede afectar a la ruta) «%1$s» importado(s). Traza guardada - Nombre del archivo vacío + Nombre de archivo vacío Revertir Un botón para hacer que la pantalla se centre en el punto de partida. Luego define el destino o activa el cálculo de la ruta. Mostrar nodo de la red de rutas ciclistas @@ -3458,7 +3458,7 @@ Velocidad mínima Precisión mínima Desplazamiento mínimo - Restablecer ajustes del complemento a valores predefinidos + Restablecer complemento a valores predefinidos División de grabación Usar la aplicación del sistema Reproducir sonido al fotografiar @@ -3835,7 +3835,7 @@ Elegir otra traza Guardar traza en archivo GPX Grabar la traza automáticamente al navegar - Intervalo de registro para la grabación general de trazas (activar mediante el widget de grabación de viaje sobre el mapa). + Intervalo de registro para la grabación general de trazas (activado desde el widget «Grabación de viaje» en el mapa). Guardar como nueva traza 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. @@ -3890,7 +3890,7 @@ Rehacer • Se ha actualizado la función «Planificar ruta»: permite utilizar diferentes tipos de navegación por segmento y la inclusión de trazas \n -\n • Nuevo menú con el aspecto de las trazas: elegir el color, el grosor, mostrar las flechas de dirección y los iconos de inicio/fin. +\n • Nuevo menú con el aspecto de las trazas: elegir el color, el grosor, mostrar las flechas de dirección y los iconos de inicio y fin. \n \n • Mejoras en la visibilidad de los nodos de bicicleta. \n @@ -3906,7 +3906,7 @@ Nombre: Z – A Nombre: A – Z Último modificado - Iconos de inicio/fin + Iconos de inicio y fin Gracias por comprar las «Curvas de nivel» La suscripción se cobra por el período elegido. Puedes cancelarlo en cualquier momento en AppGallery. El pago será cargado a la cuenta de AppGallery al confirmar la compra. @@ -3922,7 +3922,7 @@ Datos de «OsmAnd Live» Datos de «OsmAnd Live» Navegación compleja - Inicia sesión con OAuth para usar las funciones de edición de OSM + Ingresar con OAuth para usar las funciones de edición de OSM Ingresar a través de OAuth Sesión finalizada Desarrollo @@ -3948,27 +3948,27 @@ Emergencia Comodidad El archivo ya fue importado en OsmAnd - Iniciar sesión - Usar nombre de usuario y contraseña + Ingresar + Ingresar con usuario y contraseña Hay un problema con la suscripción. Pulsa el botón para ir a los ajustes de la suscripción de Google Play y corregir el método de pago. La suscripción a OsmAnd Live se ha pausado La suscripción a OsmAnd Live está en espera La suscripción a OsmAnd Live ha caducado Ingresar con OpenStreetMap Enviar archivo GPX a OpenStreetMap - Debes iniciar sesión para subir cambios nuevos o modificados. + Debes iniciar sesión para subir los cambios nuevos o modificados. \n -\nPuedes ingresar usando el método seguro de OAuth o usar el nombre de usuario y contraseña. +\nPuedes ingresar usando el método seguro de OAuth o con nombre de usuario y contraseña. Debes añadir al menos dos puntos Historial de marcadores Gestionar suscripción - Ingresar a OpenStreetMap.org + Ingresar en OpenStreetMap.org Iniciar sesión en OpenStreetMap Cuenta - Trazable significa que la traza no aparecerá en ninguna lista pública pero el conjunto de puntos estarán disponibles a través de la API pública de GPS y con marcas de tiempo. Otros usuarios sólo podrán descargar el conjunto de puntos procesados de su traza que no se pueden asociar directamente con usted. - Público significa que la traza se mostrará públicamente en tu listado de trazas y en los listados de trazas GPS públicas. Los datos servidos a través de la API no harán referencia a su página de trazas. Las marcas de tiempo de los puntos de la traza no estarán disponible a través de la API pública de GPS, aunque los puntos se ordenan cronológicamente. Sin embargo, otros usuarios podrán descargar la traza en bruto de la lista de trazas públicas y las marcas de tiempo que contiene. - Privado significa que la traza no aparecerá en ninguna lista pública, pero el conjunto de puntos seguirá estando disponible en orden cronológico a través de la API pública de GPS y sin marcas de tiempo. - Identificable significa que la traza se mostrará públicamente en tu listado de trazas y en el listado de trazas GPS públicas, es decir que otros usuarios podrán descargar la traza en bruto y asociarla con su nombre de usuario. Los datos servidos a través de la API de conjunto de puntos hará referencia a la página original de la traza. Las marcas de tiempo de los puntos de la traza estarán disponibles a través de la API pública de GPS. + «Trazable» significa que la traza no aparece en ninguna lista pública, pero el conjunto de puntos procesados con marcas de tiempo (no se pueden asociar directamente con usted) estarán disponibles a través de la API pública de GPS. + «Público» significa que la traza se mostrará públicamente en tu listado de trazas y en los listados de trazas GPS públicas con marcas de tiempo en bruto. Los datos servidos a través de la API no harán referencia a su página de trazas. Las marcas de tiempo de los puntos de la traza no estarán disponible a través de la API pública de GPS, aunque los puntos se ordenan cronológicamente. + «Privado» significa que la traza no aparecerá en ninguna lista pública, pero el conjunto de puntos seguirá estando disponible en orden cronológico a través de la API pública de GPS y sin marcas de tiempo. + «Identificable» significa que la traza se mostrará públicamente en tu listado de trazas y en el listado de trazas GPS públicas, es decir que otros usuarios podrán descargar la traza en bruto y asociarla con su nombre de usuario. Los datos servidos a través de la API de conjunto de puntos hará referencia a la página original de la traza. Ingresa etiquetas separadas por comas. Añadir foto Ya tengo cuenta @@ -3979,4 +3979,26 @@ Puedes iniciar sesión con el método seguro de OAuth o usar el nombre de usuario y contraseña. Comentar nota de OSM Cerrar nota de OSM + Historial de búsqueda + Recursos + Marca los datos que serán exportados al archivo. + Necesario para importar + El dispositivo sólo tiene %1$s libre. Por favor, libera algo de espacio o desmarca algunos elementos a exportar. + Sin espacio suficiente + Tamaño aproximado del archivo + Lancha a motor + Kayak + Añadir a OpenPlaceReviews + Añadir a Mapillary + OsmAnd muestra fotos de varios repositorios: +\nOpenPlaceReviews (fotos de PDI); +\nMapillary (imágenes a nivel de calle); +\nWeb / Wikimedia (fotos de PDI incluidas en los datos de OpenStreetMap). + Cambia a la versión para desarrolladores «dev.openstreetmap.org» en lugar de openstreetmap.org para probar la carga de PDI, notas de OSM y archivos GPX. + Usar dev.openstreetmap.org + Elegir imagen + Marca los elementos que serán importados. + Marca los grupos que serán importados. + No se puede subir la imagen, inténtalo más tarde + Separador \ No newline at end of file diff --git a/OsmAnd/res/values-es/strings.xml b/OsmAnd/res/values-es/strings.xml index efe9166106..c4f61547c4 100644 --- a/OsmAnd/res/values-es/strings.xml +++ b/OsmAnd/res/values-es/strings.xml @@ -3897,4 +3897,48 @@ Último modificado Nombre: Z – A Nombre: A - Z + MGRS + Novedades + MGRS + OsmAnd usa MGRS, que es similar al formato UTM NATO. + Iconos de inicio y fin + Desarollo + El fichero ya está importado en OsmAnd + Mapas locales + %1$s — %2$s + Servicio + Especial + Transporte + Servicio + Símbolos + Deporte + Emergencia + Viajar + Necesita añadir al menos dos puntos + Cuenta + Nombre de usuario + Gestionar suscripción + Enviar fichero GPX a OpenStreetMap + Introduzca las etiquetas separadas por una coma. + Cerrar Nota de OSM + Comentar Nota de OSM + Añadir foto + Registrar en +\nOpenPlaceReviews.org + Crear cuenta nueva + Ya tengo una cuenta + Historial de búsqueda + Kayak + Lancha a motor + Añadir a Mapillary + Añadir a OpenPlaceReviews + OsmAnd muestra fotos de diferentes fuentes: +\nOpenPlaceReviews - fotos POI; +\nMapillary - imágenes a nivel de calle; +\nWeb / Wikimedia - fotos POI especificadas en los datos de OpenStreetMap. + Recursos + Tamaño de fichero aproximado + Seleccione los datos para exportar al fichero. + Necesario para importar + No hay espacio suficiente \ No newline at end of file diff --git a/OsmAnd/res/values-et/phrases.xml b/OsmAnd/res/values-et/phrases.xml index 97af8c5b8c..279982921e 100644 --- a/OsmAnd/res/values-et/phrases.xml +++ b/OsmAnd/res/values-et/phrases.xml @@ -3832,4 +3832,9 @@ Parkimine varjualustes Parkla katusel Radarimast + Residents + Nuntsiatuur + Saatkond + Konsulaat + Saatkond \ No newline at end of file diff --git a/OsmAnd/res/values-eu/phrases.xml b/OsmAnd/res/values-eu/phrases.xml index 0bb27ef42b..5d48a182e9 100644 --- a/OsmAnd/res/values-eu/phrases.xml +++ b/OsmAnd/res/values-eu/phrases.xml @@ -1749,7 +1749,7 @@ Oin-sendagile Zerga aholkularien bulegoa Ice stock kirola - Korfbal + Korfball Paddle tenisa Erraketa (kirol tresna) Errugbi elkartea @@ -2592,7 +2592,7 @@ Motorizatua Bonba gabekoa Minerala - Uraren ezaugarria: lokatza + Lokatza Sulfurikoa Ur-puntua Poste adierazlea @@ -3549,18 +3549,18 @@ Zailtasun-kategoria н/к н/к* - + 1A 1А* - - 1Б* - - 2А* - - 2Б* - - 3А* - - 3Б* + 1B + 1B* + 2A + 2A* + 2B + 2B* + 3A + 3A* + 3B + 3B* Ezabatutako objektua Erradioterapia Bai @@ -3789,7 +3789,7 @@ Kabina mota Bai Ez - Zutoina aurkitzeko seinalea + Internet sarbidea: Bezeroak Ibiltzea baimenduta dagoenean soilik Kontrastatua Primitiboa @@ -3803,7 +3803,7 @@ Ur maila: boladaka Edateko ura betetzeko sarea Edateko ura betetzeko: ez - Edateko ura betetzeko: bai + Bai Trabatzea Ur maila: batezbestekotik behera Ur maila: batezbestekotik gora diff --git a/OsmAnd/res/values-eu/strings.xml b/OsmAnd/res/values-eu/strings.xml index abd30d80ff..3a3565a83b 100644 --- a/OsmAnd/res/values-eu/strings.xml +++ b/OsmAnd/res/values-eu/strings.xml @@ -1,15 +1,15 @@ - Deskargatutako zoomak: %1$s - Iraungitze epea (minutuak): %1$s + Deskargatutako zoom mailak: %1$s + Iraungitze denbora (minutuak): %1$s Deskargagarria: %1$s Zoom maximoa: %1$s Zoom minimoa: %1$s Tesela datuak: %1$s %1$s tesela iturburua gorde da - Mercator eliptikoa + Mercator eliptikoa proiekzioa Gehieneko zoom-a - Iraungitze epea (minutuak) + Iraungitze denbora (minutuak) Gutxieneko zoom-a URL Aukeratu badagoena… @@ -21,12 +21,12 @@ EEBB Kanada Europa, Asia, Hego Amerika eta antzekoak - Erresuma Batua, India edo antzekoa + Erresuma Batua, India eta antzekoak Iragarri… - Ezarri iragarpenak: Kaleen izenak, trafiko abisuak (geldialdi behartuak, abiadura mugak), radarren iragarpena. + Ezarri iragarpenak: Kaleen izenak, trafiko abisuak (geldialdi behartuak, abiadura murriztaileak), Abiadura-kameren iragarpena, eta abiadura mugak. Kaleen izenak (TTS) Abiadura muga - Radarrak + Abiadura-kamerak Trafiko abisuak Zehaztu OSM erabiltzailea eta pasahitza \'Ezarpenak\' atalean Garbitu erdibideko puntuak @@ -228,7 +228,7 @@ Turistentzako Gasolina Erakutsi alarmak… - Ezarri trafiko abisuak (abiadura mugak, geldialdi behartuak, abiadura aldaketak, tunelak), abiadura-radar abisuak eta erraien informazioa. + Ezarri trafiko abisuak (abiadura mugak, geldialdi behartuak, abiadura aldaketak, tunelak), abiadura-kameren abisuak eta erraien informazioa. Erabili iparrorratza bestelako norabiderik antzematen ez denean. Erabili iparrorratza Autobiderik ez @@ -238,27 +238,27 @@ Atxikitu errepidera OsmAnd Maps & Nabigazioa Mapa ikusle eta nabigatzaile mugikor globala lineaz kanpoko eta sare bidezko OSM mapetarako - OsmAnd (OSM Automated Navigation Directions) -\n -\nOsmAnd kode irekiko software bidezko nabigaziorako aplikazioa da, OpenStreetMapeko (OSM) mota askotako munduko mapetara sarbidearekin. Mapa guztiak (bektore edo tesela mapak) telefonoaren memoria txartelean gorde daitezke, lineaz kanpoko erabilpena bermatzeko. OsmAndek ere lineaz kanpoko eta sareko ibilbide-kalkulua eskaintzen du, txandakako ahots gidaritzarekin. -\n -\nEzaugarri nagusi batzuk: -\n- Lineaz kanpoko erabateko erabilpena (bektore edo tesela mapak gorde ondoren aukeratu daitezken karpetetan) -\n- Lineaz kanpoko mundu guztiko mapa konpaktuak eskuragarri -\n- Herrialde edo eskualdeetako mapen deskarga, aplikaziotik zuzenean -\n- Gain-geruza desberdin asko ikusi daitezke, GPX edo ibilbide bidea, interes puntuak (POI), gogokoak, sestra-kurbak, garraio publikoaren geltokiak, geruza gardeneko mapa gehigarriak. -\n- Lineaz kanpoko helbide eta lekuen bilatzailea (POI-ak) -\n- Lineaz kanpoko ibilbide-kalkulua distantzia ertainetarako -\n- Kotxea, bizikleta eta oinezkoentzat modua: -\n- Egun/gau ikuspegi automatizatua -\n- Abiaduraren araberako maparen zooma -\n- Maparen lerrokatzea, iparrorratzaren edo norabidearen araberakoa -\n- Errei gidaritza, abiadura muga bistaratzea, grabatutako edo testutik-ahotsera ahotsekin -\n -\nOsmAndeko dohaineko bertsioaren mugak -\n- Mapa kopuruak deskargatzeko muga -\n- Wikipediako POIetara lineaz kanpoko sarbiderik ez -\n + OsmAnd (OSM Automated Navigation Directions) +\n +\nOsmAnd kode irekiko software bidezko nabigaziorako aplikazioa da, OpenStreetMapeko (OSM) mota askotako munduko mapetara sarbidearekin. Mapa guztiak (bektore edo tesela mapak) telefonoaren memoria txartelean gorde daitezke, lineaz kanpoko erabilpena bermatzeko. OsmAndek ere lineaz kanpoko eta sareko ibilbide-kalkulua eskaintzen du, txandakako ahots gidaritzarekin. +\n +\nEzaugarri nagusi batzuk: +\n- Lineaz kanpoko erabateko erabilpena (bektore edo tesela mapak gorde ondoren aukeratu daitezken karpetetan) +\n- Lineaz kanpoko mundu guztiko mapa konpaktuak eskuragarri +\n- Herrialde edo eskualdeetako mapen deskarga, aplikaziotik zuzenean +\n- Gain-geruza desberdin asko ikusi daitezke, GPX edo ibilbide bidea, interesguneak, gogokoak, sestra-kurbak, garraio publikoaren geltokiak, geruza gardeneko mapa gehigarriak. +\n- Lineaz kanpoko helbide eta lekuen bilatzailea (POI-ak) +\n- Lineaz kanpoko ibilbide-kalkulua distantzia ertainetarako +\n- Kotxea, bizikleta eta oinezkoentzat modua: +\n- Egun/gau ikuspegi automatizatua +\n- Abiaduraren araberako maparen zooma +\n- Maparen lerrokatzea, iparrorratzaren edo norabidearen araberakoa +\n- Errei gidaritza, abiadura muga bistaratzea, grabatutako edo testutik-ahotsera ahotsekin +\n +\nOsmAndeko dohaineko bertsioaren mugak +\n- Mapa kopuruak deskargatzeko muga +\n- Wikipediako POIetara lineaz kanpoko sarbiderik ez +\n \nOsmAnd aktiboki garatua izaten ari da eta proiektuaren prozesuak dituen garatze, programatze eta funtzionalitate berrien probak egiteko behar den finantziazio laguntzetan ere oinarritzen da. OsmAnd+ erosiz gero, aplikazioa are zirraragarria izatea laguntzen duzu! Ezaugarri berriak finantzatzea edo dohaintza orokor bat egitea posible da osman.net-en. OsmAnd+ Mapak & Nabigazioa Lineaz Kanpoko eta Sare Bidezko OSM Mapetarako Mapa Ikusle eta Nabigatzaile Mugikor Globala @@ -283,7 +283,7 @@ \n- Aukerazko maparen lerrokatzea, iparrorratzaren edo norabidearen araberakoa \n- Aukerazko errei gidaritza, abiadura muga bistaratzea, grabaketa edo ahots bihurgailua motorra⏎ ⇥ \n - Sortu POI iragazkia + Sortu interesguneen iragazkia Garraio modua: Garraio modua: Egunsentia: %1$s ⏎\nIlunabarra: %2$s @@ -322,7 +322,7 @@ Desblokeatu Pantaila blokeatuta dago Esnatze tartea ezarri: - Radarrak + Abiadura-kamerak Trafiko abisuak Bidesaririk ez Jarraitu aurreko amaitu gabeko nabigazioaren jarraipena egiten? (%1$s segundo) @@ -378,7 +378,7 @@ Erakutsi xehetasun gehiago mapan Ibilbide datuak Formatua - POI (Point of interest) bilaketa + Interesguneen (POI) bilaketa Helbide bilaketa Koordenatuak Bilatu garraio publikoa @@ -411,7 +411,7 @@ Gehigarriak Gehigarriek ezarpen aurreratuak eta funtzionalitate berriak aktibatzen dituzte. Gehigarriak - Egin OSM ekarpenak, esaterako POI objektuak sortzea edo eraldatzea, OSM oharrak irekitzea edo komentatzea, eta sortutako GPX fitxategiak bidaltzea, aplikazioan OSM kredentzialak zehaztuta. OpenStreetMap.org elkarlanean egindako, domeinu publikoko mapa proiektu global bat da. + Egin OSM ekarpenak, esaterako interesgune objektuak sortzea edo eraldatzea, OSM oharrak irekitzea edo komentatzea, eta sortutako GPX fitxategiak bidaltzea, aplikazioan OSM kredentzialak zehaztuta. OpenStreetMap.org elkarlanean egindako, domeinu publikoko mapa proiektu global bat da. Ziurrenik bektore mapak azkarrago kargatu. Baliteke gailu batzuetan ongi ez funtzionatzea. Aukeratu ahotsa eta probatu iragarpenak erreproduzituz: OsmAnd garapena @@ -476,15 +476,15 @@ Gelditu iragarpen automatikoa Hemen nago Aldatu maparen zooma trackball-aren mugimendu horizontalaren bidez. - Trackball-a erabili zooma kontrolatzeko + Erabili trackball-a zooma kontrolatzeko Irisgarritasun hobespenak. Irisgarritasuna Aukeratutako area erakusteko ez dago memoria nahikorik Gain-azal fluoreszenteak Erabili kolore fluoreszenteak lorratzak eta ibilbideak bistaratzeko. Lineaz kanpoko edizioa - Erabili beti lineaz kanpoko edizioa. - Aplikazioaren barneko POI aldaketek ez diete deskargatutako mapa-fitxategiei eragiten, aldaketak zure gailuko fitxategi batean gordetzen dira. + Lineaz kanpoko edizioa aktibatuta badago, aldaketak lokalean gordeko dira eta eskatutakoan igoko dira, bestela aldaketak berehala igoko dira. + Aplikazioan interesguneei egindako aldaketek ez diete deskargatutako mapa-fitxategiei eragiten, aldaketak zure gailuko fitxategi batean gordetzen dira. Igotzen… {0} POI/ohar igo dira Guztia igo @@ -493,15 +493,15 @@ OSM edizio asinkronoa: OSM POI/oharrak gailuan gordeta Erakutsi eta kudeatu gailuko datu-baseko OSM POI/oharrak. - Aukeratu sare bidezko jarraipeneko tartea. - Sare bidezko jarraipen tartea + Zehaztu sare bidezko jarraipenaren tartea. + Sare bidezko jarraipenaren tartea Zehaztu web helbidea ondorengo parametroen sintaxiarekin: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}. - Sare bidezko jarraipeneko web helbidea + Sare bidezko jarraipenaren web helbidea Gorde lorratza GPX trepeta erabiliz edo \'Bidaiaren grabaketa\' ezarpenen bidez. Erakutsi uneko lorratza %1$s mapa deskargatu edo eguneratu ditzakezu. Doainezko bertsioa - Erakutsi POI-aren deskripzioa. + Erakutsi interesgunearen deskripzioa. Ipar Amerika Ipar Amerika - Estatu Batuak Amerika zentrala @@ -530,7 +530,7 @@ Aplikazioaren ezarpen globalak Zure OSM erabiltzailea Beharrezkoa openstreetmap.org-eko bidalketentzat. - Zure OSMeko pasahitza + Pasahitza Atzeko plano modua OsmAnd bigarren planoan dabil pantaila itzalia dagoen bitartean. Ez dago leku nahikorik %1$s MB deskargatzeko (%2$s libre). @@ -558,11 +558,11 @@ Simulazioa hasiarazi Ezin da fitxategia izenez aldatu. Badago izen berdineko beste fitxategi bat. - Lotutako hainbat POI kategoria aurkitu dira. + Erlazionatutako hainbat interesgune-kategoria aurkitu dira. Deskargatu lineaz kanpoko datuak interesezko puntuak bilatzeko. Izenez bilatu - \'%1$s\' POI datuen fitxategia erredundantea da eta ezabatua izan daiteke. - POI aldaketak mantentzeko fitxategi lokala ez da aurkitu eta ezin izan da sortu. + \'%1$s\' interesguneen datuen fitxategia erredundantea da eta ezabatu daiteke. + Interesguneen aldaketak mantentzeko fitxategi lokala ez da aurkitu eta ezin izan da sortu. OsmAnd+ berritu Deskargatu aplikazioaren bertsio berria mapa-fitxategi berriak erabili ahal izateko. Izenez aldatu @@ -607,14 +607,14 @@ Aktibatu Desaktibatu Deskargatu - POI datuak + Interesguneen datuak Helbide datuak Garraio publikoaren datuak Mapa datuak Desaktibatuta Ahots iragarpenak (TTS) Ahots iragarpenak (grabatua) - POI datuak + Interesguneen datuak TTS ahotsa Bilaketa Berria Mapako izenen letra-tamaina: @@ -627,12 +627,12 @@ Instalatutako Android TTS (text-to-speech) motorrak ez du aukeratutako hizkuntza jasaten, lehenetsitako TTS hizkuntza erabiliko da. Beste TTS motor bat bilatu nahi duzu merkatuan\? Falta diren datuak Deskargatu hautatutako hizkuntza? - Alderantzikatu GPXaren noranzkoa + Alderantzikatu lorratzaren noranzkoa Erabili uneko helmuga Pasatu lorratz osotik - Lineaz kanpoko bektore mapa bat dago kokapen honentzat. ⏎ -⇥⏎ -⇥Erabiltzeko, aktibatu \'Menua\' -> \'Konfiguratu mapa\' -> \'Maparen Iturburua…\' -> \'Lineaz kanpoko bektore mapak\'. + Lineaz kanpoko bektore mapa bat dago kokapen honentzat. +\n +\nErabiltzeko, aktibatu \'Menua\' -> \'Konfiguratu mapa\' -> \'Maparen Iturburua…\' -> \'Lineaz kanpoko bektore mapak\'. Ahots gidaritzaren irteera Hautatu ahots gidaritzarako bozgorailua. Ahots deiaren audioa (Kotxearen BlueTooth musika ekipoa eteteko) @@ -703,7 +703,7 @@ Garraioa Helbidea indexatzen… Mapa indexatzen… - POI indexatzen… + Interesguneak indexatzen… Garraioa indexatzen… I/O errorea km @@ -756,8 +756,8 @@ Ezin izan da marrazlea kargatu. Bektore marrazlea Aukeratu marrazketaren itxura - Erakutsi POI-aren webgunea - Erakutsi POI-aren telefonoa + Erakutsi interesgunearen webgunea + Erakutsi interesgunearen telefonoa idatzi iragazteko Erresoluzio handiko bistaratzea Ez luzatu (eta lausotu) mapa teselak erresoluzio handiko bistaratzetan. @@ -774,7 +774,7 @@ Aldatu POI-a Ezabatu POI-a Ipar-orratzaren norabidean - Mugimenduaren noranzkoan + Mugimenduaren norabidea Biraketa gabe (iparra beti gorantza) Maparen lerrokatzea: Maparen orientazioa @@ -787,19 +787,19 @@ Ezin izan da GPX kargatu. Bidali informea Ezin izan da deskargatutako maparik aurkitu memoria txartelean. - Idatzi POI bat bilatzeko + Idatzi interesgune bat bilatzeko Edozein Eskerrik asko Yandex trafikoari buruzko informazioagatik. Yandex trafikoa Ibilbidea Gogokoak OSM oharrak (sarean) - POI gainazala… + Interesguneen gainazala… Maparen iturburua… Mapa geruzak Bilatu POI-a Erabili trackball gailu bat mapa mugitzeko. - Trackball-a erabili + Erabili trackball-a Ezarri onartutako gehieneko itxarote denbora kokapenaren irakurketa bakoitzarentzat. Kokapen irakurketarako gehieneko itxarote denbora Non nago? @@ -865,12 +865,12 @@ Garraioa ADOS Erakutsi garraio publikoaren geltokiak mapan. - Erakutsi garraioaren geltokiak + Erakutsi garraio geltokiak OsmAnd nabigazio aplikazioa - POI datuak eguneratuta ({0} kargatu dira) - Ezin izan da POI zerrenda lokala eguneratu. + Interesguneen datuak eguneratuta ({0} kargatu dira) + Ezin izan da interesguneen zerrenda lokala eguneratu. Ezin izan dira datuak zerbitzaritik kargatu. - Ez dago lineaz kanpoko POI daturik area honentzat + Ez dago lineaz kanpoko interesguneen daturik area honentzat Zooma hurbiltzeak POI-ak eguneratzea ahalbidetzen dizu Eguneratu POI-a Eguneratu datu lokalak Internet bidez? @@ -947,8 +947,8 @@ Ezarpenak Gorde uneko lorratza GPX fitxategi gisa orain. Gorde uneko lorratza - Erregistroen tartea nabigazioan - Zehaztu erregistratze maiztasuna nabigazio bitarteko lorratz grabaketarako + Erregistro- tartea nabigazioan zehar + Zehaztu erregistro-tartea nabigazio bitarteko lorratz grabaketarako GPX lorratza automatikoki gordeko da lorratzen direktorioan nabigazioan zehar. Mapa eguneratu Tesela birkargatu @@ -965,8 +965,8 @@ Erakutsi ikuspegiaren norabidea Gaitu maparen 3D ikuspegia. 3D Mapa Ikuspegia - Erakutsi erabilitako azken POI-a gain-azala. - Erakutsi POI gainazala + Erakutsi erabilitako azken interesguneen gainazala. + Erakutsi interesguneen gainazala Aukeratu sareko edo cacheko mapa teselen iturburua. Tesela maparen iturburua Maparen iturburua @@ -1005,7 +1005,7 @@ Eraikina Bidegurutzatzen den kalea Mapa eguneratu - Sortu POI bat + Sortu interesgune bat Bai Utzi Aplikatu @@ -1024,7 +1024,7 @@ Iruzkina gehituta Ezin izan da iruzkina gehitu. Editatu POI-a - Sortu POI bat + Sortu interesgune bat Ezin da nodoa aurkitu, edo zerbitzua hainbat nodoz osatuta dago, eta ez dago horretarako euskarririk oraindik. {0} ezabatu (iruzkina)? Ezabatu POI-a @@ -1038,7 +1038,7 @@ Nodoari buruzko informazioa ez da kargatu Ireki Iruzkina utzi - POI-a aldatzea + Interesgunea aldatzea Beste etiketa guztiak kontserbatu dira Bidali Garbitu @@ -1176,7 +1176,7 @@ %1$s \nPuntu %1$s -Lorratza %2$s +\n%2$s lorratza Gogokoak Nire lekuak arrosa @@ -1456,7 +1456,7 @@ Lorratza %2$s Mapen biltegiratzea Kopiatu Iragazi izenez - Idatzi denetarik bilatzeko + Idatzi bilatzeko Ireki A-GPS informazioa Kudeatu @@ -1548,7 +1548,7 @@ Lorratza %2$s OsmAnd ibilbidearen lineaz kanpoko kalkulua Ibilbidearen kalkulu azkarrak huts egin du (%s), kalkulu motelera aldatzen. Ibilbide birkalkulatze adimentsua - Bidai luzeetan, birkalkulatu ibilbidearen hasierako partea besterik ez. + Ibilbidearen hasierako partea birkalkulatzen du soilik. Bidai luzeetan erabili daiteke. Hautatu nabigazioan saihestu nahi dituzun errepideak. Errepideak besterik ez Errepide estiloa @@ -1596,7 +1596,7 @@ Lorratza %2$s \n{3} MB behar dira une batez, {1} MB behin betiko. ({2} MB eskuragarri.) Igo zure OSM oharra era anonimoan edo zure OpenStreetMap.org profila erabiliz. Bistaratu mendiko bizikletarako bideak - POI ikonoak + Interesguneen ikonoak Grabaketaren banatzea Erabili grabaketaren banatzea Gainidatzi atalak erabilitako espazioa biltegiratze espazioa baino handiagoa bada. @@ -1605,7 +1605,7 @@ Lorratza %2$s Grabatutako atal guztiekin okupatu daitekeen espazioa. Hautatu ahots bidezko gidaritza Hautatu zure hizkuntzaren ahots bidezko gidaritza. - Zehaztu POI mota egokia edo saltatu. + Zehaztu interesgune mota egokia edo saltatu. Menu botoiak kontrol panela abiatzen du, ez menua \'Desgaituta\' dagoenean mapa abiatzen da zuzenean. Bistaratu posizioa beti erdian @@ -1626,8 +1626,8 @@ Lorratza %2$s Mundu oinarri mapa Sareko OSM mapa klasifikazioa irudiekin. - Herrialde askotan (Besteak beste Alemania, Frantzia Italia...) Radar abisuak jasotzea legez debekatuta dago. OsmAndek ez du erantzukizunik onartuko legea jarraitzen ez baduzu. Mesedez sakatu \'Bai\' soilik ezaugarri hau erabiltzeko eskubidea baduzu. - Radarra + Herrialde askotan (Besteak beste Alemania, Frantzia Italia...) abiadura-kameren abisuak jasotzea legez debekatuta dago. OsmAndek ez du erantzukizunik onartuko legea jarraitzen ez baduzu. Mesedez sakatu \'Bai\' soilik ezaugarri hau erabiltzeko eskubidea baduzu. + Abiadura-kamera Koordenatuen formatua Koordenatu geografikoen formatua. Autobus @@ -1653,7 +1653,7 @@ Lorratza %2$s Albaniera (Tosk) OSM POI-a sortuta %1$sko mapa erabili dezakezu orain. - Fitxategiaren izenak karaktere baliogaberen bat du + Fitxategi-izenak karaktere baliogaberen bat du Erakutsi %1$s mapan Bilatu %1$sra OsmAnd bidez partekatua @@ -1749,7 +1749,7 @@ Lorratza %2$s Deskargatu mapa berria Kudeatu Maparen hizkuntza - Garraioaren geltokiak + Garraio geltokiak Zonaldea Eskuragarri Eguneraketak @@ -1807,7 +1807,7 @@ Lorratza %2$s Erakutsi zoom botoiak Gorde gogokoen talde gisa Ezarri helburuak - POI gainazalaren etiketak + Interesguneen gainazalaren etiketak Serbokroaziera Navajoa Tamilera @@ -1829,7 +1829,7 @@ Lorratza %2$s Erradioa Erregistro tarte orokorra Kokaleku orokorra GPX fitxategian erregistratzea gaitu eta desgaitu daiteke mapako GPX erregistro trepetarekin. - Erregistroaren tartea + Erregistro-tartea Gaitu HTTP proxya Konfiguratu HTTP proxya sare eskaera guztietarako. Proxy ostalaria @@ -1867,7 +1867,7 @@ Lorratza %2$s Eguneratu Erabili menua Maparen legenda - Ziur POI puntua mota gabe gorde nahi duzula? + Ziur interesgunea mota gabe gorde nahi duzula\? Eraldatu OSM aldaketa Bertsioak Artikulu teknikoak @@ -1937,14 +1937,14 @@ mapak eta nabigazioa Itxiera ordua Kontaktu informazioa Gehitu irekiera orduak - POI mota + Interesgune mota Paneleko errenkada kopurua %1$s - Zehaztu POI mota mesedez. + Zehaztu interesgune mota mesedez. Lanegunak Azken tokiak Gogokoak Orain hemen gordeta: %1$s - Aldaketak igotzen dituzunean POI-a ezabatuko da + Aldaketak igotzen dituzunean interesgunea ezabatuko da Lerro kopurua Ziur zaude? Gorde gabeko aldaketak galduko dira, Jarraitu? @@ -2015,7 +2015,7 @@ mapak eta nabigazioa Mapak deskargatzeko beharrezkoa da. Kokalekua bilatzen… Espazio librea - OsmAnd datuen biltegiratzea (mapak, GPX fitxategiak, eta abar): %1$s. + OsmAnd datuen biltegiratzea (mapak, lorratz fitxategiak, eta abar): %1$s. Eman baimena Eman kokapena atzitzeko baimena Jaso jarraibideak eta aurkitu toki berriak Internet konexiorik gabe @@ -2044,18 +2044,18 @@ mapak eta nabigazioa Azpikategoriak Transliteratu %1$s izena falta bada Transliteratu izenak - Idatzi hiria, helbidea, POI izena + Idatzi hiria, helbidea, interesgunearen izena Marroi argia Marroi iluna Ingerada marren kolore eskema Errepidearen gainazalaren integritatea Ingerada marren kolore eskema - Gutxieneko abiadura erregistratzeko + Erregistratzeko abiadura minimoa Iragazkia: Ez erregistratu puntuak abiadura honen azpitik. Erregistratzeko desplazamendu minimoa Iragazkia: Ezarri puntu berri bat erregistratzeko gutxieneko distantzia. - Erregistratzearen gutxieneko zehaztasuna - Iragazkia: Ez erregistratu zehaztasun hau ez badago. + Erregistratzeko zehaztasun minimoa + Iragazkia: Ez erregistratu zehaztasun hau lortu arte. Eguberriko POI Eguberria eta urte berria datozela, zerikusia duten puntuak bistaratzea erabaki dezakezu, eguberri zuhaitzak, merkatuak, eta abar. Erakutsi eguberriko puntuak\? @@ -2069,10 +2069,10 @@ mapak eta nabigazioa Bistaratu bidaiaren grabaketa ahalbidetzen duen jakinarazpen bat. Jakinarazpenak Hartu %1$d. irteera eta jarraitu - Igo POI bat + Igo interesgune bat Ibilbidearen kalkulua - Ez duzu GPX fitxategirik oraindik - GPX fitxategiak karpetara gehitu ditzakezu ere + Ez duzu lorratz fitxategirik oraindik + Lorratz fitxategiak karpetara gehitu ditzakezu ere Gehitu gehiago… Itxura Ongi @@ -2130,7 +2130,7 @@ Area honi dagokio: %1$s x %2$s Pantailaren erdian bideo-ohar bat gehitzeko botoia. Pantailaren erdian argazki-ohar bat gehitzeko botoia. Pantailaren erdian OSM ohar bat gehitzeko botoia. - Pantailaren erdian POI bat gehitzeko botoia. + Pantailaren erdian interesgune bat gehitzeko botoia. Nabigazioan ahots bidezko jarraibideak gaitu edo desgaitzeko botoia. Pantailaren erdian aparkaleku bat gehitzeko botoia. " hona gorde da: " @@ -2149,8 +2149,8 @@ Area honi dagokio: %1$s x %2$s Mezua Gogokoa gordetzeko kategoria: Aukeratu hautazko kategoria. - POI zerrenda - Gehitu POI kategoria bat edo gehiago mapan erakusteko. + Interesguneen zerrenda + Gehitu interesguneen kategoria bat edo gehiago mapan erakusteko. Azpiko zerrendaren hurrengo orria erakusteko botoia. Gehitu mapa estilo bat Bete parametro guztiak @@ -2174,7 +2174,7 @@ Area honi dagokio: %1$s x %2$s Ekintzaren izena Bikoizketa ekiditeko ekintza azkarrari %1$s izena jarri zaio. Gogoko puntuak mapan erakutsi edo ezkutatzeko botoia. - POI puntuak mapan erakutsi edo ezkutatzeko botoia. + Interesguneak mapan erakutsi edo ezkutatzeko botoia. Laga hutsik helbidea edo lekuaren izena erabiltzeko. Automatikoki zatitu grabaketa hutsunea eta gero Hasi segmentu berria 6 minututako hutsune bat eta gero, lorratz berria bi ordu eta gero, edo fitxategi berria hutsune luzeago bat eta gero data aldatzean. @@ -2184,7 +2184,7 @@ Area honi dagokio: %1$s x %2$s Puntuak ezabatu dira. Ziur %1$d puntu ezabatu nahi dituzula\? Ibilbide honetan pasatu beharreko bide-gurutzeak - Bide-puntuak, interesezko puntuak, izena duten ezaugarriak + Bide-puntuak, interesguneak, izena duten ezaugarriak Lorratza Gehieneko abiadura Batezbesteko abiadura @@ -2257,9 +2257,9 @@ Area honi dagokio: %1$s x %2$s Berreskuratu erosketak Maparen letra-tipoak Pausatua - OsmAnd (OSM Automated Navigation Directions) mapa eta nabigazio aplikazio bat da. Doako, mundu osoko eta kalitate altuko OSM mapak eskura jartzen dizkizuna. + OsmAnd (OSM Automated Navigation Directions) mapa eta nabigazio aplikazio bat da. Doako, mundu osoko eta kalitate altuko OSM mapak eskura jartzen dizkizuna. \n -\nGozatu ahots bidezko nabigazioa edo nabigazio grafikoa, ikusi interesezko puntuak (POI), sortu eta kudeatu GPX lorratzak, erabili sestra-kurbak eta garaiera datuak (gehigarri baten bidez), aukeratu kotxe, bizikleta eta oinezko moduen artean, editatu OSM, eta askoz gehiago. +\nGozatu ahots bidezko nabigazioa edo nabigazio grafikoa, ikusi interesguneak (POI), sortu eta kudeatu GPX lorratzak, erabili sestra-kurbak eta garaiera datuak (gehigarri baten bidez), aukeratu kotxe, bizikleta eta oinezko moduen artean, editatu OSM, eta askoz gehiago. Idatzi helbidea GPS nabigazioa \n• Lineaz kanpo (Ibiltaritza kargurik ez atzerrian zaudenean) edo konektatuta (azkarragoa) aritzea erabaki dezakezu @@ -2335,7 +2335,7 @@ Area honi dagokio: %1$s x %2$s Piztu \'Nire posizioa\'-ren mugimendu animatua nabigazioan. %1$s barne "Eskiatu -\nOsmAnd eski-mapak gehigarriak eskiatzeko ibilbideak ikustea baimentzen dizu, konplexutasun mailarekin eta bestelako informazio gehigarriarekin, arrasteak eta bestelako zerbitzuak." +\nOsmAnd eski-mapak gehigarriak eskiatzeko pistak ikustea baimentzen dizu, konplexutasun mailarekin eta bestelako informazio gehigarriarekin, arrasteak eta bestelako zerbitzuak." Hartu parte OSMn \n• Eman datuen arazoen berri \n• Igo GPX lorratzak OSMra aplikaziotik bertatik @@ -2362,14 +2362,15 @@ Area honi dagokio: %1$s x %2$s Gora/Behera Denbora mugimenduan Max/Min - Mapa -\n• Bistaratu inguruko interesezko puntuak (POI) -\n• Egokitu mapa zure mugimenduaren (edo iparrorratzaren) norabidera -\n• Non zauden eta nora begiratzen duzun erakusten du -\n• Partekatu zure kokalekua lagunek zu aurkitu ahal izateko -\n• Gorde zuretzat garrantzitsuak diren tokiak gogokoetan -\n• Mapan izenak nola bistaratu aukeratzen uzten dizu: zure hizkuntzan, tokiko hizkuntzan, edo ahoskera fonetikoa -\n• Interneteko tesela mapak erakusten ditu, satelite ikuspegia (Bingek eskainia), hainbat gainazal, esaterako turismorako edo nabigaziorako GPX lorratzak eta azal gehigarriak gardentasun aldagarriarekin + Mapa +\n• Bistaratu inguruko interesguneak (POI) +\n• Egokitu mapa zure mugimenduaren (edo iparrorratzaren) norabidera +\n• Non zauden eta nora begiratzen duzun erakusten du +\n• Partekatu zure kokalekua lagunek zu aurkitu ahal izateko +\n• Gorde zuretzat garrantzitsuak diren tokiak gogokoetan +\n• Mapan izenak nola bistaratu aukeratzen uzten dizu: zure hizkuntzan, tokiko hizkuntzan, edo ahoskera fonetikoa +\n• Interneteko tesela mapak erakusten ditu, satelite ikuspegia (Bingek eskainia), hainbat gainazal, esaterako turismorako edo nabigaziorako GPX lorratzak eta azal gehigarriak gardentasun aldagarriarekin +\n Bizikleta \n• Bizikletentzako bideak aurki ditzakezu mapan \n• Bizikletarako GPS nabigazioak ibilbideak bizikletentzako bideak erabiliz eraikiko du @@ -2452,14 +2453,14 @@ Area honi dagokio: %1$s x %2$s Erakutsi \'nabigazioa amaituta\' elkarrizketa-koadroa Hasi/amaitu nabigazioa Nabigazioa hasi edo amaitzeko botoia. - Lineako jarraipenaren denbora-bufferra + Sare bidezko jarraipenaren denbora-bufferra Zehaztu bidaltzeke dauden kokalekuak gordetzeko denbora-buffer bat Mapillary-ko argazkiak linean besterik ez daude eskuragarri. Saiatu berriro Neurtu distantzia Arakatu mapa eta gehitu puntuak Gehitu puntu bat gutxienez. - GPX fitxategiaren izena: + GPX fitxategi-izena: Erakutsi mapan gorde eta gero Gehitu bide-puntua Gorde GPX bide-puntua @@ -2481,7 +2482,7 @@ Area honi dagokio: %1$s x %2$s Desgaitu maparen animazioak. Jarraitu mapan erakusten Irten gorde gabe? - Gorde puntuak puntu ala lerro gisa. + Gorde puntuak bide-puntu ala lerro gisa. OsmAndek puntuak hautatutako profilaren ibilbideekin lotuko ditu. Hautatu nabigazio profila Gehitu ibilbide-puntuak @@ -2622,16 +2623,16 @@ Area honi dagokio: %1$s x %2$s Negua eta eskia Bidaiatze ikuspegia Nautikoa - POI etiketak + Interesguneen etiketak Bihar irekiko du ordu honetan - Kopiatu kokaleku edo POI-aren izena + Kopiatu kokaleku edo interesgunearen izena Izen gabeko kokalekua Unekoa Tarteko geldialdia gehitzen du Lehen geldialdia gehitzen du Mugitu helburua gora, eta sortu Erakutsi itxitako oharrak - Erakutsi/ezkutatu OSM oharrak mapan. + Erakutsi edo ezkutatu OSM oharrak mapan. GPX - JOSM edo bestelako OSM editoreentzat esportatzeko egokia. OSC - OSM-ra esportatzeko egokia. GPX fitxategia @@ -2751,7 +2752,7 @@ Area honi dagokio: %1$s x %2$s Gogokoa Eskuratu OsmAnd Live ezaugarri guztiak desblokeatzeko: Mapen eguneraketak egunero deskarga mugarik gabe, ordainpeko eta doako gehigarri guztiak, Wikipedia, Wikivoyage eta askoz gehiago. Lehenetsitako itxuraren aldaera, oinezko eta bizikleten bideen kontrastea handitzeko. Mapnik kolore zaharrak erabiltzen ditu. - Errepidetik kanpo gidatzeko, \'Topo\' estiloan oinarritua atzealdean sateliteko irudiekin erabiltzeko. Errepide nagusien zabalera estutua, eta bide, bidexka eta bidegorrien zabalera handitua. + Errepidetik kanpo gidatzeko, \'Topo\' estiloan oinarritua atzealdean sateliteko irudiekin erabiltzeko. Errepide nagusien zabalera estutua, eta pista, bidexka eta bidegorrien zabalera handitua. Nabigazio nautikorako. Ezaugarri nagusiak: Boiak, faroak, ibai bideak, itxas erreiak eta markak, portuak, itsas zerbitzuak, sakonera marrak. Eskiatzeko. Ezaugarri nagusiak: Pistak, arrasteak eta abar. Bestelako mapako objektuak leuntzen dira. Gidatzeko estilo sinplea. Begietara xamurra gau moduan, sestra-kurbak, kontraste handiko errepide laranjak, bestelako mapako objektuak leunduak. @@ -2898,7 +2899,7 @@ Area honi dagokio: %1$s x %2$s Aldatu Erakutsi gehiago Bistaratutako lorratzak - Erakutsi/ezkutatu GPX lorratzak + Erakutsi/ezkutatu lorratzak Gehitu tarteko puntua %1$d transferentzia Gehitu irteera eta helburua @@ -2936,8 +2937,8 @@ Area honi dagokio: %1$s x %2$s Eskailera Bidea Zehaztu gabea - Ezkutatu GPS lorratzak - Erakutsi GPS lorratzak + Ezkutatu lorratzak + Erakutsi lorratzak Gehitu helburua aurretik Aurreko ibilbidea Graduak @@ -2952,7 +2953,7 @@ Area honi dagokio: %1$s x %2$s Trinkotua Zaldi-bidea Bizikletentzako bidea - Hautatutako GPX lorratzak mapan erakutsi edo ezkutatzeko botoia. + Hautatutako lorratzak mapan erakutsi edo ezkutatzeko botoia. Tranbiarik ez Ekidin tranbiak Autobusik ez @@ -3234,7 +3235,7 @@ Area honi dagokio: %1$s x %2$s Mapa nabigazioan zehar Mapa nabigazioan zehar Beste bat - Pisua, altuera, abiadura + Pisua, altuera, luzera, abiadura Ibilgailuaren parametroak Ahots iragarpenak nabigazioan zehar egiten dira soilik. Nabigazio argibideak eta iragarpenak @@ -3310,7 +3311,7 @@ Area honi dagokio: %1$s x %2$s %1$s GB %1$s MB %1$s KB - Lorratzek gordetzeko karpeta + Lorratzak gordetzeko karpeta Lorratzak \'rec\' karpetan edo hilabeteko zein eguneko karpetatan gorde daitezke. Grabatu lorratzak \'rec\' karpetan Grabatu lorratzak eguneko karpetetan @@ -3420,12 +3421,12 @@ Area honi dagokio: %1$s x %2$s Hautatu ikonoa, kolorea eta izena Kokalekua partekatzeko aukera bidai grabaketa erabiliz. Lineako jarraipena - Egunkariaren zehaztasuna + Erregistroaren zehaztasuna Egiaztatu eta partekatu aplikazioaren erregistro zehatzak Baimena beharrezkoa da aukera hau erabiltzeko. - Hau abiadura txikiko atalase iragazkia da, abiadura jakin baten azpitik puntuak ez erregistratzeko. Grabatutako ibilbideak leunagoak izan daitezke mapan ikusitakoan. - Albo-efektua: Zure ibilbidean gutxieneko abiadura irizpidea betetzen ez duten zati guztiak faltako zaizkizu (adibidez, bizikletaz aldapa bat igotzen duzunean). Gainera, ez da atsedenaldi-epeei buruzko informaziorik egongo,. Horrek edozein azterketeta edo post-prozesuri eragingo dio, adibidez, bidaiaren guztizko iraupena, denbora martxan, edo batez besteko abiadura zehazten saiatzean. - Gomendioa: Saiatu lehenbizi mugimenduaren detekzioa erregistroko gutxieneko desplazamendu iragazkiaren bidez (B), emaitza hobeak sor ditzake eta datu gutxiago galduko dituzu. Zure ibilbideak abiadura baxuan zaratatsuak badira, saiatu zeroz kanpoko balioak hemen. Kontuan izan behar da neurketa batzuek ez dutela abiadura balioa emango (sarean oinarritutako metodo batzuk), kasu horretan ez zenuke ezer grabatuko. + Hau abiadura txikiko atalase iragazkia da, abiadura jakin baten azpitik puntuak ez erregistratzeko. Grabatutako lorratzak leunagoak izan daitezke mapan ikusitakoan. + Albo-efektua: Zure lorratzak gutxieneko abiadura irizpidea betetzen ez duten zati guztiak faltako zaizkizu (adibidez, bizikletaz aldapa bat igotzen duzunean). Gainera, ez da atsedenaldi-epeei buruzko informaziorik egongo,. Horrek edozein azterketeta edo post-prozesuri eragingo dio, adibidez, bidaiaren guztizko iraupena, denbora martxan, edo batez besteko abiadura zehazten saiatzean. + Gomendioa: Saiatu lehenbizi mugimenduaren detekzioa erregistroko gutxieneko desplazamendu iragazkiaren bidez (B), emaitza hobeak sor ditzake eta datu gutxiago galduko dituzu. Zure lorratzak abiadura baxuan zaratatsuak badira, saiatu zeroz kanpoko balioak hemen. Kontuan izan behar da neurketa batzuek ez dutela abiadura balioa emango (sarean oinarritutako metodo batzuk), kasu horretan ez zenuke ezer grabatuko. Oharra: abiadura> 0 egiaztatzea: GPS txip gehienek algoritmoak mugimenduan zaudela zehazten duenean bakarrik adierazten dute abiaduraren balioa, eta deus ez bestela. Hori dela eta, iragazki honetan > 0 ezarpena erabiltzean GPS txiparen mugimendua detekzioa erabiltzen duzula esan daiteke. Baina grabaketa garaian hemen iragazi ez bada ere, funtzio hau erabiltzen dugu gure GPX azterketan zuzendutako distantzia zehazteko, hau da, eremu horretan erakutsitako balioa mugimenduan grabatutako distantzia da. Honek gutxieneko zehaztasun adierazlearekin neurtutako puntuak soilik erregistratuko ditu (metro edo oinetan, Android-ek zure txiperako jakinarazi duen moduan). Zehaztasuna neurketa eta egiazko posizioaren arteko hurbiltasuna da, ez dago prezisioarekin lotua, hori errepikatutako neurketen sakabanaketa da. Albo-efektua: Zehaztasunaren arabera iragaztearen ondorioz, puntuak falta daitezke, adibidez, zubien azpian, zuhaitzen azpian, eraikin altuen artean, edo eguraldi jakin batzuekin. @@ -3458,9 +3459,9 @@ Area honi dagokio: %1$s x %2$s \n \n• Beste profil bateko ezarpenak kopiatzeko aukera gehitu da \n -\n• Ordena aldatzeko edo POI kategoriak ezkutatzeko aukera gehitu da +\n• Ordena aldatzeko edo interesgune kategoriak ezkutatzeko aukera gehitu da \n -\n• POI ikonoak mapan behar bezala lerrokatuta +\n• Interesgune ikonoak mapan behar bezala lerrokatuta \n \n• Ilunabarra / egunsentia datuak gehitu da maparen konfigurazioan \n @@ -3509,15 +3510,15 @@ Area honi dagokio: %1$s x %2$s Ibilbidearen birkalkulua Iragarri Erabiltzaile-izena eta pasahitza - Ezarpen hauek profil guztiei aplikatzen zaizkie. + Ezarpen hauek orokorrak dira, eta profil guztiei aplikatzen zaizkie. OSM edizioa - Ikusi zure aldaketak edo oraindik igo gabeko OSM akatsak hemen: %1$s. Igotako puntuak ez dira gehiago erakutsiko. + Oraindik igo gabeko aldaketak edo OSM akatsak hemen ikusi ditzakezu: %1$s. Igotako puntuak ez dira OsmAnd-en erakutsiko. OSM Nabigatu edo mugitzean erakutsitako ikonoa. Atsedenean erakutsitako ikonoa. Ezin izan da \'%s\' geo intent-a errendatu. Oharra: Grabatzen hasi aurretik GPSa itzalita egon bada, neurtutako lehen puntuak zehaztasun txikia izan dezake. Gure kodean puntu bat grabatu aurretik segundo bat itxaron genezake (edo jarraian grabatutako hirutik onena hartu, etab.), baina oraindik ez da hau garatu. - Iragazki honek puntu bikoiztuak grabatzea saihesten du mugimendu txikiegia egon bada. Gero prozesatu ez diren ibilbideetan itxura hobe bat lortzen da. + Iragazki honek puntu bikoiztuak grabatzea saihesten du mugimendu txikiegia egon bada. Gero prozesatu ez diren lorratzetan itxura hobe bat lortzen da. Albo ondorioak: Atseden aldiak ez dira batere erregistratzen edo puntu bakarrarekin erregistratzen dira. Mugimendu txikiak (adibidez, albo batera) iragazi daitezke. Zure fitxategiak informazio gutxiago dauka post-prozesatzeko eta estatistika txarragoakk ditu erregistratzeko garaian puntu erredundanteak iragazi dituelako, agian harrera txarra edo GPS txiparen efektuak eragindako akatsak mantentzen dituen bitartean. Gomendioa: 5 metroko ezarpenak ondo funtziona dezake zuretzat, hori baino gehiagoko xehetasuna behar ez baduzu, eta ez badituzu esplizituki jaso nahi atseden aldiko datuak. Denbora-bufferra @@ -3536,7 +3537,7 @@ Area honi dagokio: %1$s x %2$s Ordenatu kategoriaren arabera Antartika Prestatzen - POI motak + Interesgune motak Ez da ezer hautatu Ekintza azkarrak Profilak @@ -3578,7 +3579,7 @@ Area honi dagokio: %1$s x %2$s Mapako terreno geruza erakutsi edo ezkutatzeko botoia. Erakutsi terrenoa Ezkutatu terrenoa - Erakutsi / ezkutatu terrenoa + Erakutsi edo ezkutatu terrenoa Maldak Erliebea Gaitu erliebea edo malda mapa ikusteko. Mapa mota hauei buruz gehiago irakur dezakezu gure gunean @@ -3611,9 +3612,9 @@ Area honi dagokio: %1$s x %2$s Kolore pertsonalizatua Mapa gehigarriak onartu gabeko ekintza %1$s - Sortu / aldatu POIa + Sortu edo aldatu interesgunea Aparkaleku-posizioak - Gehitu / aldatu gogokoa + Gehitu edo aldatu gogokoa Berrezarri lehenetsitako ordena Itzuli ediziora Ekintza botoiak hautatutako profilen artean txandakatzen du. @@ -3623,12 +3624,12 @@ Area honi dagokio: %1$s x %2$s Munduaren gainbegirada mapa (xehetsua) Onartu gabeko mota Garraio publikoa mapan erakutsi edo ezkutatzen duen botoia. - Hautatu mapan agertuko diren Wikipediako artikuluen hizkuntzak. Hizkuntza eskuragarrien artean txandakatu dezakezu artikulua irakurtzean. + Hautatu mapako Wikipediako artikuluen hizkuntzak. Hizkuntza eskuragarrien artean txandakatu dezakezu artikulua irakurtzean. Wikipediako artikulu batzuk agian ez daude zure hizkuntzan eskuragarri. Malgaxea Aragonera %1$s / %2$s - Bilatu POI motak + Bilatu interesgune motak OsmAnd + Mapillary Ekintza azkarra Erradioaren erregela @@ -3642,8 +3643,8 @@ Area honi dagokio: %1$s x %2$s Nabigazio profilak Ezkutatu garraio publikoa Erakutsi garraio publikoa - Erakutsi/ezkutatu garraio publikoa - OsmAnd Aztarnaria + Erakutsi edo ezkutatu garraio publikoa + OsmAnd aztarnaria Jarraitu Pertsonalizatu \"Tiradera\", \"Konfiguratu mapa\" eta \"Laster-menua\" ataletan dauden elementu kopurua. \n @@ -3695,7 +3696,7 @@ Area honi dagokio: %1$s x %2$s \n Harpidetza automatikoki berrituko da berritze data baino lehen bertan behera uzten ez bada. Berritze-aldian (hilabetea / hiru hilabetea / urtea) kobratuko da kontua. \n \n Zure harpidetzak kudeatu eta bertan behera utzi ditzakezu Google Play ezarpenetara joanez. - Konbinatu kategoria desberdinetako POI motak. Ukitu pizgailua guztiak hautatzeko, ukitu ezkerreko aldea kategoria aukeratzeko. + Konbinatu kategoria desberdinetako interesgune motak. Ukitu pizgailua guztiak hautatzeko, ukitu ezkerreko aldea kategoria aukeratzeko. • Lineaz kanpoko malda-mapa berriak \n \n • Gogokoen eta GPX bide-puntuen pertsonalizazio osoa - kolore, ikono, eta forma pertsonalizatuak @@ -3704,7 +3705,7 @@ Area honi dagokio: %1$s x %2$s \n \n • Wikipedia bereizitako geruza gisa \"Konfiguratu mapa\" atalean, hautatu behar diren hizkuntzak soilik \n -\n • Sortu zure POI iragazkia / mapak malgutasun osoz +\n • Sortu zure interesguneen iragazkia / mapak malgutasun osoz \n \n • Aukerak gehitu profil pertsonalizatuetarako ezarpenak leheneratzeko \n @@ -3739,7 +3740,7 @@ Area honi dagokio: %1$s x %2$s Iraungitze ordua Mercator proiekzioa Biltegiratze formatua - Ezarri zoom maila minimo eta maximoa lineaz kanpoko mapa bistaratu edo kargatzeko. + Ezarri zoom maila minimo eta maximoa sareko mapa bistaratu edo kargatzeko. Parametro hauek bistaratzeari eragingo diote maparen gainazal edo azpiazal gisa erabiltzean. \n \n%1$s: Mapa hautatutako zoom mailetara mugatuko da. @@ -3761,7 +3762,7 @@ Area honi dagokio: %1$s x %2$s Eman zure ibilgailuaren pisua, ibilgailu astunentzako zenbait ibilbide murriztu daitezke. Desgaituta. \"Mantendu pantaila piztuta\" behar da \"Esnatu ondorengo denbora-muga\" atalean. metro - Kontrolatu mapan agertzen diren xehetasun gehigarrien ikusgaitasuna + Erakutsi edo ezkutatu maparen xehetasun gehigarriak Gauerako mapa Erakutsi/ezkutatu Mapillary Ezkutatu Mapillary @@ -3775,28 +3776,228 @@ Area honi dagokio: %1$s x %2$s Gurpil-aulkia Kart Puntuen arteko ibilbidea - Gehitu arrasto batera + Gehitu lorratz batera Hautatu zabalera Hautatu zatiketa aukera: denboraren arabera edo distantziaren arabera. Norabideko geziak Sortu ibilbide berria Distantzia margena - Aukera hau erabiltzeko OsmAnd-ek zure arrastoak mapako errepideetara atxiki behar ditu. -\n -\nHurrengo urratsean, nabigazio profila hautatu beharko duzu baimendutako errepideak eta zure arrastoa errepideetara hurbiltzeko distantzia tartea atzemateko. + Ondoren, lotu zure lorratza baimendutako errepiderik hurbilenera zure nabigazio profil batekin aukera hau erabiltzeko. Editatutako azkena - Inportatu arrastoa - Ireki dagoen arrasto bat - Hautatu irekitzeko arrasto fitxategia - Gainidatzi arrastoa - Gorde arrasto berri gisa + Inportatu lorratza + Ireki dagoen lorratz bat + Hautatu irekitzeko lorratz fitxategia. + Gainidatzi lorratza + Gorde lorratz berri gisa Alderantzizko ibilbidea - Arrasto osoa birkalkulatuko da hautatutako profilaren bidez. - Bakarrik hurrengo segmentua birkalkulatuko da hautatutako profilaren bidez. - Hautatu nola konektatu puntuak, lerro zuzen batez, edo kalkulatu horien arteko ibilbidea hautatutako profilarekin. - Arrasto osoa + Lorratz osoa birkalkulatuko da hautatutako profilaren bidez. + Bakarrik hurrengo segmentua birkalkulatuko da hautatutako profila erabiliz.. + Aukeratu nola konektatu puntuak, lerro zuzen batez, edo kalkulatu horien arteko ibilbidea behean adierazitako moduan. + Lorratz osoa Hurrengo segmentua Nabigazio profila - Hautatu zein arrasto fitxategiari gehituko zaion segmentu berria. - Ezarri behar dituzu lanegunak jarraitzeko + Hautatu zein lorratz fitxategiari gehituko zaion segmentu berria. + Ezarri lanegunak jarraitzeko + Gehitu argazkia + Sortu kontu berria + Kontu bat daukat dagoeneko + Bilaketa-historia + Kayak + Motor itsasontzia + Gehitu Mapillary-ra + Baliabideak + Fitxategiaren tamaina gutxi gorabehera + Hautatu fitxategira esportatuko diren datuak. + Inportatzeko beharrezkoa da + Zure gailuak %1$s soilik ditu libre. Mesedez, askatu espazioa edo desautatu esportatzeko elementu batzuk. + Ez dago espazio nahikorik + Motoa + Zehaztu lorratz orokorreko grabazio erregistroaren tartea (mapan \'Bidaia grabaketa\' trepetaren bidez aktibatuta dago). + Ireki gordetako lorratza + \"Jarraigarria\" esan nahi du lorratza ez dela inolako zerrenda publikoetan agertzen, baina prozesatutako puntuak bere denbora markekin (zurekin zuzenean lotu ezin direnak) GPS API publikoaren deskargen bidez agertzen dira. + + Prestazioa + OpenStreetMap-eko saio hasiera + OpenStreetMap.org-eko saio hasiera + \"Publikoa\" esan nahi du lorratza publikoki erakusten dela zure GPS lorratzen eta GPS lorratz zerrende publikoetan, eta lorratzen zerrenda publikoan denbora markak modu gordinean daudela. APIaren bidez hornitutako datuek ez dute zure lorratz orria aipatzen. Bide-puntuen denbora-zigiluak ez daude eskuragarri GPS API publikoaren bidez, eta bide-puntuak ez daude kronologikoki ordenatuta. + \"Pribatua\" esan nahi du lorratza ez dela inolako zerrenda publikoetan agertzen, baina ordena ez kronologikoan dauden bide-puntuak GPS API publikoaren bidez eskuragarri daude denbora-markarik gabe. + \"Identifikagarria\" esan nahi du lorratza publikoki erakutsiko dela Zure GPS lorratzetan eta GPS lorratz zerrenda publikoetan, hau da, beste erabiltzaileek lorratz gordina deskargatu eta zure erabiltzaile izenarekin lotu ahal izango dute. Bide-puntuen APIaren bidez hornitutako GPS APIaren denbora-markadu bide-puntuak jatorrizko lorratzari egingo diote erreferentzia. + Erregistratu lorratza automatikoki nabigazioan zehar + MGRS + Zer dago berri + Elur-motorra gidatzeko, berezko bide eta lorratzekin. + MGRS + OsmAnd-ek MGRS erabiltzen du, UTM NATO formatuaren antzekoa da. + Eman zure ibilgailuaren luzera, ibilbide batzuetako mugak aplika daitezke ibilgailu luzeentzat. + Herrialde edo eskualde batzuetan, abiadura-kamerak abisatzeko aplikazioak erabiltzea legez debekatuta dago. +\n +\nAukeraketa bat egin behar duzu zure herrialdeko legediaren arabera. +\n +\nAukeratu %1$s eta abiadura-kamerei buruzko alertak eta abisuak jasoko dituzu. +\n +\nAukeratu %2$s eta abiadura-kameraen inguruko datu guztiak, alertak, jakinarazpenak, interesguneak ezabatuko dira OsmAnd erabat berriro instalatu arte. + Mapillary geruza mapan erakutsi edo ezkutatzeko botoia. + Moztu ondoren + • Eguneratutako ibilbidea planifinatzeko funtzioa: Segmentu bakoitzeko nabigazio mota desberdinak erabiltzea eta lorratzak sartzea ahalbidetzen du +\n +\n • Lorratzen itxura menu berria: Hautatu kolorea, lodiera, bistaratzeko norabideko geziak, hasierako eta amaierako ikonoak +\n +\n • Bizikleta nodoen ikusgarritasuna hobetu da. +\n +\n • Orain lorratzetan sakatu daitezke, laster-menua dute oinarrizko informazioarekin. +\n +\n • Bilaketa algoritmoak hobetu dira +\n +\n • Lorratza jarraitzeko aukerak hobetu dira nabigazioan +\n +\n • Profilaren ezarpenak inportatzeko / esportatzeko arazoak konpondu dira +\n +\n + Azken aldaketa + Izena: Z - A + Izena: A - Z + Hasiera eta amaiera ikonoak + Eskerrik asko \"Sestra lerroak\" erosteagatik + Harpidetza kobratuta hautatutako aldirako. Utzi AppGallery-n edozein unetan. + Ordainketa zure AppGallery kontuan kargatuko da erosketa baieztatzean. +\n +\nHarpidetza automatikoki berritzen da, berritze data baino lehen bertan behera utzi ezean. Berritze aldia (hilean / hiru hilean / urtean) berrituko den egunean bertan kobratuko zaizu. +\n +\nHarpidetzak kudeatu eta bertan behera utzi ditzakezu AppGallery-ren ezarpenetara joanda. + Hasi saioa OAuth-ekin osmedit funtzioak erabiltzeko + Hasi saioa OAuth bidez + Garbitu OpenStreetMap OAuth token-a + Saioa amaitu da + Fitxategia dagoeneko OsmAnd-en inportatuta dago + Erabili 2 faseko A* bideratze algoritmoa + Grafikoa + Hasi saioa aldaketak igotzeko, +\n +\nbai OAuth-ekin edo zure erabiltzaile izena eta pasahitza erabiliz. + Hasi saioa erabiltzaile izenarekin eta pasahitzarekin + Kontua + Hasi saioa + Kudeatu harpidetza + Arazo bat dago zure harpidetzarekin. Egin klik botoian Google Play harpidetzaren ezarpenetara joateko zure ordainketa-metodoa konpontzeko. + OsmAnd Live harpidetza iraungi egin da + OsmAnd Live harpidetza pausatu da + OsmAnd Live harpidetza zain dago + Sartu etiketak komaz bereizita. + Hasi saioa OAuth metodo segurua erabiliz edo erabili zure erabiltzaile izena eta pasahitza. + Erregistratu hemen: +\nOpenPlaceReviews.org + Hasi saioa OpenPlaceReviews.org datu irekien proiektuaren webgunean, argazki gehiago igotzeko. + Gehitu OpenPlaceReviews-era + OsmAnd-ek hainbat iturritako argazkiak erakusten ditu: +\nOpenPlaceReviews - Interesguneen argazkiak; +\nMapillary - Kale mailako irudiak; +\nWeb / Wikimedia - OpenStreetMap datuetan zehaztutako interesguneen argazkiak. + Norabidea + Moztu aurretik + Lorratzaren grabazioa pausatuko du aplikazioa hiltzean (azken aplikazioen bidez). (OsmAnd atzeko planoaren adierazpena Androideko jakinarazpen-barratik desagertzen da.) + Pausatu bidaiaren grabazioa + Berrekin bidaiaren grabazioa + Sisteman lehenetsia + Ondorengo segmentu guztiak + Aurreko segmentua + Aurreko segmentu guztiak + Aukeratutako segmentua soilik birkalkulatuko da hautatutako profila erabiliz. + Ondorengo segmentu guztiak birkalkulatuko dira hautatutako profila erabiliz. + Aurreko segmentu guztiak berriro kalkulatuko dira hautatutako profila erabiliz. + gorde da + Gehitu gutxienez bi puntu. + Berregin + Bidaia + Gutxienez bi puntu gehitu behar dituzu + Hasi saioa OpenStreetMap-ekin + Gehitu lorratzaren bide-puntua + Gehitu lorratzaren bide-puntua + Bidaiaren grabaketa + Gorde lorratz fitxategi gisa + Jarraitu lorratza + Hautatu jarraituko den lorratzaren fitxategia + Aukeratu jarraituko den lorratzaren fitxategia edo inportatu zure gailutik. + Aukeratu beste lorratz bat + Nabigatu nire posiziotik lorratzera + Nabigatzeko lorratzaren puntua + Lorratzaren hasiera + Puntu hurbilena + Erantsi errepideetara + Ezabatu helbidea + Gehitu helbidea + Sartu helbidea + Aldatu ibilbide mota honen aurretik: + Aldatu ibilbide mota honen ondoren: + Lorratz sinplifikatua + Ibilbidearen lerroa bakarrik gordeko da, bide-puntuak ezabatuko dira. + Fitxategi-izena + %s lorratz fitxategi aukeratuta + GRABATU + Saihestu oinezkoen bideak + Saihestu oinezkoen bideak + Garapena + OsmAnd zuzeneko datuak + OsmAnd zuzeneko datuak + Bi faseetako ibilbide kalkulua kotxe bidezko nabigazioarentzat. + Garraio publikoaren garapen natiboa + Aldatu garraio publikoaren ibilbidearen kalkulua Javara (segurua) + %1$s datuak soilik errepideetan soilik daude eskuragarri, eskuratzeko ibilbidea kalkulatu behar duzu \"Puntuen arteko ibilbidea\" erabiliz. + Itxaron ibilbidea berkalkulatu arte. +\nGrafikoa erabilgarri egongo da berkalkulatu ondoren. + Tokiko mapak + %1$s — %2$s + Berezia + Garraioa + Zerbitzua + Sinboloak + Kirola + Larrialdia + Abiadura-kameren interesguneak + Gailu honek ez du abiadura-kamerarik. + Desinstalatu abiadura-kamerak + Legezkoa + Mantendu aktibo + Desinstalatu + Abiadura-kameren alertak herrialde batzuetan legeak debekatuta daude. + tonuak + Gehitu sareko iturria + Aldaketa hauek aplikatzean lauzen iturburu honetako cache datuak garbituko dira + Ezarri ontziaren altuera + Ontziaren altuera ezar dezakezu zubi baxuak ekiditeko. Gogoan izan, zubia mugikorra bada, irekita dagoeneko altuera erabiliko dugula. + Ezarri ontziaren altuera zubi baxuak ekiditeko. Gogoan izan, zubia mugikorra bada, irekita dagoeneko altuera erabiliko dugula. + Ezarri ontziaren zabalera zubi estuak ekiditeko + Zehaztu ibilbideetan baimendutako ibilgailu-luzera. + Luzera muga + %1$s ezabatuta + Berrabiarazi aplikazioa abiadura-kameraren datu guztiak ezabatzeko. + Desinstalatu eta berrabiarazi + Lerroko patinak + Kontrolatu maparen zoom maila gailuaren bolumen botoiekin. + Eman izena puntuari + Deskargatu Wikipediako mapak + Gehitutako puntua ez da mapan ikusiko, hautatutako taldea ezkutatuta dagoelako, \"%s\" atalean aurkitu dezakezu. + Itxitako OSM oharra + Planifikatu ibilbidea + Erakutsi hasierako eta amaierako ikonoak + Aukeratu markatzaileak lorratzean bistaratzeko tartea distantzian edo denboran. + Pertsonalizatua + Solidoa + Kale mailako irudiak + Ziur al zaude aurreikusitako ibilbidean egindako aldaketa guztiak baztertu nahi dituzula eta itxi\? + Alderantzizko norabidearen kasuan + Gorde lorratz fitxategi berri gisa + Gehitu lorratz fitxategi batean + Lorratzak + Lorratzak + Lorratzak + Erregistratu lorratza GPX fitxategian + Lorratz ibilbidea + Gehitu lorratz fitxategiak + Inportatu edo grabatu lorratz fitxategiak + Itxi OSM oharra + Markatzaileen historia + Bidali GPX fitxategia OpenStreetMap-era + Egin iruzkina OSM oharrean + Hautatu argazkia + Erabili dev.openstreetmap.org \ No newline at end of file diff --git a/OsmAnd/res/values-fa/strings.xml b/OsmAnd/res/values-fa/strings.xml index f08461e509..e657b192aa 100644 --- a/OsmAnd/res/values-fa/strings.xml +++ b/OsmAnd/res/values-fa/strings.xml @@ -3980,4 +3980,11 @@ خصوصی یا Private به این معنی است که رد در هیچ‌یک از لیست‌های عمومی نشان داده نمی‌شود اما نقاط رد از طریق API جی‌پی‌اس‌های عمومی بدون مهر زمان و بدون ترتیب زمانی دست‌یافتنی است. قابل‌شناسایی یا Identifiable به این معنی است که رد به‌صورت عمومی در لیست ردهای جی‌پی‌اس شما و لیست عمومی ردهای جی‌پی‌اس نمایش داده می‌شود، یعنی سایر کاربران می‌توانند رد خام را دانلود کنند و بدانند که مربوط به نام کاربری شماست. دادهٔ نقاط رد که از طریق API در دسترس قرار می‌گیرد، به صفحهٔ ردهای شما ارجاع می‌دهد. مهر زمان نقاط رد از طریق API جی‌پی‌اس‌های عمومی دست‌یافتنی است. قابل‌ردیابی یا Trackable به این معنی است که رد در هیچ‌یک از لیست‌های عمومی نشان داده نمی‌شود اما نقاط رد + مهر زمان نقاط از طریق API جی‌پی‌اس‌های عمومی دست‌یافتنی است. سایر کاربران فقط می‌توانند نقاط پردازش‌شدهٔ رد شما را دانلود کنند که مستقیماً امکان ارجاع به نام کاربری شما را ندارد. + افزودن عکس + عکس‌ها از طریق پروژهٔ داده‌باز OpenPlaceReviews.org ارائه می‌شود. برای آپلود عکس‌های خود لازم است در این وبگاه ثبت نام کنید. + ثبت نام در +\nOpenPlaceReviews.org + ساخت حساب جدید + حساب کاربری دارم + تاریخچهٔ جست‌وجو \ No newline at end of file diff --git a/OsmAnd/res/values-fr/phrases.xml b/OsmAnd/res/values-fr/phrases.xml index 40f35c26d0..3afde7dc60 100644 --- a/OsmAnd/res/values-fr/phrases.xml +++ b/OsmAnd/res/values-fr/phrases.xml @@ -655,7 +655,7 @@ Club Restaurant et café Artisanat - Station essence + Station service Transport individuel Alimentation en eau potable Traitement des ordures ménagères @@ -3818,7 +3818,7 @@ Remplissage d\'eau potable : non Réseau de remplissage d\'eau potable Uniquement si la marche est autorisée - Signal pour trouver le poteau + Accès internet client Pression Aspiration Pressurisé @@ -3844,4 +3844,33 @@ Tableau des départs : non Ascenseur Tableau des départs + Liaison + Consulat + Ambassade + Point d\'eau potable + Résidence + Nonciature + Mission + Haut-commissariat + Non + Oui + Non + Oui + Non + Oui + Bureau du représentant + Bureau + Consul honoraire + Consulat général + Bureau consulaire + Agence consulaire + Dirigé(e) par un consul + Délégation + Dirigé(e) par un Ambassadeur + Ambassade + Radar tourelle + Refuge/arrêt d\'urgence + Parking couvert + Parking en terrasse + Point GPX \ No newline at end of file diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml index c48a9fb01e..ac27f7a76e 100644 --- a/OsmAnd/res/values-fr/strings.xml +++ b/OsmAnd/res/values-fr/strings.xml @@ -1,7 +1,7 @@ Modifications hors-ligne - Toujours utiliser l\'édition hors-ligne. + Si le mode d\'édition hors-ligne est activé, les modifications seront enregistrées localement puis envoyées à la demande. Sinon, les modifications seront envoyées immédiatement. Les modifications de points d\'intérêt dans l\'application sont sans effet sur les cartes téléchargées, les modifications sont enregistrées dans un fichier de votre appareil. Téléversement… {0} Points d\'intérêt / Notes ont été téléversés @@ -695,8 +695,8 @@ Dès que possible Public Identifiable - Suivi - Privé + Traçable + Privée Récupérer le véhicule au parking Avertissement Un rappel pour récupérer votre véhicule a été ajouté à votre agenda. Vous pouvez modifier ou supprimer ce rappel. @@ -1467,7 +1467,7 @@ Paramètres généraux Désélectionner - Désélectionner tout + Tout désélectionner Erreur inattendue Action {0} Vidéo @@ -1883,7 +1883,7 @@ Requis pour mettre à jour vos contributions. Nom affiché Ne pas afficher mon nom dans les rapports - Région supportée + Région du support Veuillez indiquer votre nom public Déplacer ↑ Déplacer ↓ @@ -2056,7 +2056,7 @@ Afficher une notification système permettant de démarrer l\'enregistrement de l\'itinéraire. Vous n\'avez aucun fichier de trace pour l\'instant Vous pouvez aussi ajouter des fichiers de trace GPX dans le dossier - Autre trace GPX … + Autre GPX … Apparence Bien Translittérer si le nom %1$s est absent @@ -2134,7 +2134,7 @@ Sous-couches de carte Ajouter une sous-couche Modifier la source de la carte - Sources de cartes + Sources des cartes Ajouter une source de carte Source de la carte modifiée pour « %s ». Déplacer le bouton @@ -2709,7 +2709,7 @@ Wikivoyage hors-ligne Téléchargements illimités Wikipedia hors-ligne - Activez toutes les fonctionnalités d\'OsmAnd + Débloquer toutes les fonctionnalités d\'OsmAnd Mise à jour des cartes : Tous les mois Mise à jour des cartes : Toutes les heures La validité de votre achat sera permanente. @@ -3203,7 +3203,7 @@ Apparence Greffons installés Paramétrer la navigation - Paramétrer le profil + Configurer le profil Afficher les alertes en bas à gauche de l\'écran pendant la navigation. Basculer de profil Langue et sortie @@ -3406,9 +3406,9 @@ Recalcul de l\'itinéraire Annonce Nom d\'utilisateur et mot de passe - Les paramètres du greffon sont globaux et s\'appliquent à tous les profils. + Les paramètres du greffon sont globaux et s\'appliquent à tous les profils Édition OSM - Vous pouvez consulter vos modifications non téléversées comme vos bugs OSM dans %1$s. Les points envoyés ne sont plus affichés dans OsmAnd. + Vous pouvez consulter vos modifications et vos bugs OSM non envoyés dans %1$s. Les points envoyés ne s\'affichentr plus dans OsmAnd. OSM Icône affiché pendant la navigation ou en déplacement. Icône affiché à l\'arrêt. @@ -3899,7 +3899,7 @@ Développement du transport public autochtone Connectez-vous avec OAuth Supprimer le jeton OAuth d\'OpenStreetMap - Déconnexion réussie + Déconnecté Le fichier est déjà importé dans OsmAnd Utiliser un algorithme de routage A* à 2 phases Le paiement sera débité de votre compte AppGallery dès confirmation de l\'achat. @@ -3948,11 +3948,31 @@ \nOpenPlaceReviews.org Créer un nouveau compte J\'ai déjà un compte - Vous devez vous connecter pour envoyer vos modifications. + Connectez-vous pour envoyer vos modifications, \n -\nVous pouvez vous connecter avec la méthode sécurisée OAuth ou utiliser votre identifiant et votre mot de passe. - Vous pouvez vous connecter avec la méthode sécurisée OAuth ou utiliser votre identifiant et votre mot de passe. - Les photos sont fournies par le projet open data OpenPlaceReviews.org. Pour envoyer vos photos, vous devez au préalable être inscrit sur ce site Web. +\nsoit avec OAuth soit avec votre identifiant et mot de passe. + Vous pouvez vous connecter avec la méthode sécurisée OAuth ou avec votre identifiant et votre mot de passe. + Connectez-vous au site web du projet OpenPlaceReviews.org pour ajouter des photos. Historique de recherche Kayak + Votre appareil n\'a que %1$s disponible. Veuillez libérer de l\'espace ou désélectionner l\'export pour certains éléments. + Bateau à moteur + Ressources + Taille approximative du fichier + Sélectionnez les données à exporter dans le fichier. + Nécessaire pour l\'import + L\'espace disponible est insuffisant + Ajouter à Mapillary + Ajouter à OpenPlaceReviews + OsmAnd affiche des photos de plusieurs sources : +\nOpenPlaceReviews : photos de PI ; +\nMapillary : photos de rue ; +\nWeb / Wikimedia : photos de PI réféfencés dans OpenStreetMap. + \"Privée\" signifie que la trace ne sera visible dans aucune des listes publiques, mais les points de trace qu\'elle contient seront disponibles sans horodatage et dans un ordre non-chronologique au moyen de l\'API GPS publique. + Utiliser dev.openstreetmap.org plutôt que openstreetmap.org pour tester l\'envoi des notes OSM / Points d\'intérêt / GPX. + Utiliser dev.openstreetmap.org + Sélectionnez les groupes à importer. + Sélectionnez les objets à importer. + Impossible d\'envoyer l\'image, veuillez réessayer plus tard + Sélectionnez une image \ No newline at end of file diff --git a/OsmAnd/res/values-gl/phrases.xml b/OsmAnd/res/values-gl/phrases.xml index cfb2bee6f2..1b72fedd88 100644 --- a/OsmAnd/res/values-gl/phrases.xml +++ b/OsmAnd/res/values-gl/phrases.xml @@ -796,7 +796,7 @@ Lámpadas eléctricas Poliéster Escola - Universidade + Educación superior Pediatría Tiro con arco Salón de tiro @@ -3843,4 +3843,34 @@ Terrazo Punto GPX Torre de radar + Non + Si + Non + Si + Non + Si + Subnacional + Oficina representativa + Oficina + Cónsul honorario + Consulado xeral + Oficina consular + Axencia consular + Dirixido por un cónsul + Residencia + Nunciatura + Misión + Sección de intereses + Alto comisionado + Delegación + Sucursal + Dirixido por un embaixador + Ligazón + Embaixada + Servizos ó cidadán + Visados de inmigrante + Visados de non inmigrante + Ligazón + Consulado + Embaixada \ No newline at end of file diff --git a/OsmAnd/res/values-gl/strings.xml b/OsmAnd/res/values-gl/strings.xml index f0d735e36c..c83b2f6df1 100644 --- a/OsmAnd/res/values-gl/strings.xml +++ b/OsmAnd/res/values-gl/strings.xml @@ -753,7 +753,7 @@ Sobreposicións fluorescentes Empregar cores fluorescentes para amosar as pistas e rutas. Edición sen conexión - Empregar sempre a edición sen conexión. + Se se activa a edición sen conexión, as modificacións serán gardadas de xeito local primeiro e serán cargadas por solicitude, do contrario as modificacións serán cargadas de xeito inmediato. As modificacións nos puntos de interese (PDI) dentro da aplicación non afectan ós ficheiros dos mapas baixados, pois esas modificacións gárdanse coma un ficheiro no teu dispositivo. Estase a subir… {0} PDI/notas subidos @@ -2063,7 +2063,7 @@ Lon %2$s Número de colaboradores Número de edicións Informe para - O nome do ficheiro contén un carácter incorrecto + Caráter ilegal no nome do ficheiro Acción rápida Acción %d Pantalla %d @@ -2365,7 +2365,7 @@ Lon %2$s 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. + Amosar ou agochar as notas do OSM no mapa. GPX - axeitado para exportar a JOSM ou outros editores do OSM. OSC - axeitado para exportar ó OSM. Ficheiro GPX @@ -3115,9 +3115,9 @@ Lon %2$s Muda o achegamento do mapa desprazando a roda cara arriba e abaixo. A tecla «Esc» volta á aplicación WunderLINQ. Controlar co WunderLINQ Engadir polo menos un elemento á listaxe nos axustes de \'Acción rápida\' - Esquí alpino/de descendemento + Esquí alpino e de descendemento Pistas de esquí alpino ou de descendemento e acceso a remontes mecánicos. - Esquí de travesía/nórdico + Esquí de travesía e nórdico Pistas para esquí nórdico ou de travesía. Esquí de travesía Roteiros para esquí de travesía. @@ -3385,7 +3385,7 @@ Lon %2$s Trocar %1$s e %2$s Punto de comezo Pista gardada - O nome do ficheiro está baleiro + Nome do ficheiro baleiro Reverter Un botón para facer que a pantalla se centre no punto de partida. Despois define o destino ou activa o cálculo da ruta. Amosar os nós da rede de sendas ciclistas @@ -3450,7 +3450,7 @@ Lon %2$s Nome de usuario e contrasinal Os axustes deste complemento son globais e aplícanse a todos os perfís Edición do OSM - Podes ollar todas as túas edición non subidas ou erros do OSM en %1$s. Os puntos subidos non se amosan no OsmAnd. + Podes ollar todas as túas edicións aínda non subidas ou erros do OSM en %1$s. Os puntos subidos non se amosan no OsmAnd. OSM A icona amósase mentres se navega ou se move pola pantalla. A icona amósase en asueto. @@ -3647,7 +3647,7 @@ Lon %2$s A ruta será recalculada se a distancia á localización actual é maior que o valor escollido. %1$s de %2$s Pendentes - Amosar / agochar terreo + Amosar ou agochar terreo Agochar terreo Amosar terreo Un botón que amosa ou agocha a capa do terreo no mapa. @@ -3716,11 +3716,11 @@ Lon %2$s Podes acceder a estas accións premendo no botón “%1$s”. Agochar transporte público Amosar transporte público - Amosar/agochar transporte público + Amosar ou agochar transporte público Botón que amosa ou agocha o transporte público no mapa. - Crear / Editar PDI + Crear ou editar PDI Posicións de aparcamento - Engadir / Editar favorito + Engadir ou editar favorito Restabelecer a orde dos elementos predefinidos Voltar á edición O botón de acción troca entre os perfís escollidos. @@ -3854,7 +3854,7 @@ Lon %2$s Refacer • Actualizouse a función \"Planificar ruta\": permite empregar diferentes tipos de navegación por segmento e o engadido de pistas \n -\n • Novo menú coa aparencia das pistas: escoller a cor, o grosor, amosar as frechas de dirección e as iconas de comezo/final. +\n • Novo menú coa aparencia das pistas: escoller a cor, o grosor, amosar as frechas de dirección e as iconas de inicio e final. \n \n • Melloras na visibilidade dos nós de bicicleta. \n @@ -3924,11 +3924,11 @@ Lon %2$s %s ficheiros de pista seleccionados Gravar A gravación da pista deterase ó pechar a aplicación (mediante aplicacións recentes). (A indicación de fondo do OsmAnd, desaparecerá da barra de notificacións do Android.) - Especifica o intre de gravación xeral para pistas (habilitado a través do trebello de gravación no mapa). + Especifica o intre de gravación xeral para pistas (habilitado a través do trebello de \'Gravación no mapa\'). Última modificación Nome: Z – A Nome: A – Z - Iconas de comezo/final + Iconas de inicio e fin Grazas por mercar \'Curvas de nivel\' Subscrición cobrada por período escollido. Cancélaa na AppGallery en calquera intre. O pagamento será cargado na túa conta da AppGallery no mesmo intre da confirmación da compra. @@ -3946,7 +3946,7 @@ Lon %2$s Desenvolvemento do transporte público nativo Activar cálculo de enrutamento de transporte público do Java (seguro) Novidades - Inicia sesión co OAuth para empregar as funcións de edición do OSM + Inicia a sesión co OAuth para empregar as funcións de edición do OSM Entrar polo OAuth Limpar token do OpenStreetMap OAuth Sesión rematada @@ -3977,20 +3977,50 @@ Lon %2$s A subscrición do OsmAnd Live expirou A subscrición do OsmAnd Live foi detida A subscrición do OsmAnd Live está en espera - Público significa que a pista amosarase de xeito público na túa listaxe de pistas e nas listaxes de pistas GPS públicas. Os datos servidos a través da API non farán referencia á túa páxina de pistas. As marcaxes de tempo dos puntos da pista non estarán dispoñíbeis a través da API pública de GPS, aínda que os puntos ordénanse de xeito cronolóxico. Porén, outros usuarios poderán baixar a pista en bruto da listaxe de pistas públicas e as marcaxes de tempo que contén. - Iniciar sesión no OpenStreetMap - Entrar ó OpenStreetMap.org - Entrar co OpenStreetMap - Precisas iniciar sesión para subir modificacións novas. + \"Público\" significa que a pista amosarase de xeito público na túa listaxe de pistas e nas listaxes de pistas GPS públicas con marcas de tempo en bruto. Os datos servidos a través da API no farán referencia á túa pácina de pistas. As marcaxes de tempo dos puntos da pista non estarán dispoñíbeis a través da API pública de GPS, aínda que os puntos son ordenados de xeito cronolóxico. + Iniciar a sesión ó OpenStreetMap + Iniciar a sesión ó OpenStreetMap.org + Iniciar a sesión co OpenStreetMap + Tes que iniciar sesión para subir as modificacións novas. \n -\nPodes iniciar sesión empregando o método seguro de OAuth ou empregar o nome de usuario e contrasinal. - Empregar nome de usuario e contrasinal +\nPodes iniciar sesión empregando o método seguro do OAuth ou co nombre de usuario e contrasinal. + Iniciar a sesión co usuario e contrasinal Conta Iniciar sesión Historial de marcaxes Enviar ficheiro GPX ó OpenStreetMap Insire etiquetas separadas por comas. - Privado significa que a pista non aparecerá en ningunha listaxe pública, mais o conxunto de puntos seguirá estando dispoñíbel en orde cronolóxica a través da API pública de GPS e sen marcaxes de tempo. - Rastrexábel (ou trazábel) significa que a pista non aparecerá en ningunha listaxe pública pero o conxunto de puntos estarán dispoñíbeis a través da API pública de GPS e con marcaxes de tempo. Outros usuarios só poderán baixar o conxunto de puntos procesados da túa pista que non se poden asociar directamente contigo. - Identificábel significa que a pista amosarase de xeito público na túa listaxe de pistas e na listaxe de pistas GPS públicas, é dicir que outros usuarios poderán baixar a pista en bruto e asociala co teu nome de usuario. Os datos servidos a través da API de conxunto de puntos fará referencia á páxina orixinal da pista. As marcaxes de tempo dos puntos da traza estarán dispoñíbeis a través da API pública de GPS. + \"Privado\" significa que a pista non aparecerá en ningunha listaxe pública, pero o conxunto de puntos seguirá estando dispoñíbel en orde cronolóxica a través da API pública de GPS e sen marcas de tempo. + \"Rastrexábel\" (ou \"trazábel\") significa que a pista non aparece en ningunha listaxe pública, pero o conxunto de puntos procesados con marcas de tempo (non se poden asociar directamente contigo) estarán dispoñíbeis a través da API pública de GPS. + \"Identificábel\" significa que a pista amosarase de xeito público na túa listaxe de pistas e na listaxe de pistas GPS públicas, é dicir que outros usuarios poderán baixar a pista en bruto e asociala co seu nome de usuario. Os datos servidos a través da API de conxunto de puntos fará referencia á páxina orixinal da pista. + Pechar nota do OSM + Comentar nota do OSM + Podes iniciar a sesión co método seguro do OAuth ou emprega o nome de usuario e contrasinal. + Engadir imaxe + Rexistrarse no +\nOpenPlaceReviews.org + As imaxes son fornecidas polo proxecto de datos abertos do OpenPlaceReviews.org. Para subir a túas imaxes precisas rexistrarte no sitio web. + Crear nova conta + Xa teño unha conta + Historial de procura + Caiac + Lancha a motor + Recursos + Tamaño aproximado do ficheiro + Marca os datos que serán exportados ó ficheiro. + Necesario para importar + O teu dispositivo só ten %1$s libre. Por favor, libera algo de espazo ou desmarca algúns elementos a exportar. + Sen espazo dabondo + Non é posíbel subir a imaxe, por favor, téntao novamente máis tarde + Seleccionar imaxe + Seleccionar os grupos que serán importados. + Seleccionar os elementos que serán importados. + Engadir ó Mapillary + Engadir ó OpenPlaceReviews + Mudar á versión para desenvolvedores dev.openstreetmap.org no canto do openstreetmap.org para probar a carga de PDI, notas do OSM e ficheiros GPX. + Empregar dev.openstreetmap.org + O OsmAnd amosa imaxes de diferentes fontes: +\nOpenPlaceReviews - imaxes POI; +\nMapillary - maxes a nivel de rúa; +\nWeb / Wikimedia - imaxes POI especificadas nos datos do OpenStreetMap. \ No newline at end of file diff --git a/OsmAnd/res/values-hu/phrases.xml b/OsmAnd/res/values-hu/phrases.xml index f6fe9f9bfe..726efe646c 100644 --- a/OsmAnd/res/values-hu/phrases.xml +++ b/OsmAnd/res/values-hu/phrases.xml @@ -606,7 +606,7 @@ Papírbolt Autógumibolt State Emergency Service (állami vészhelyzeti szolgálat), AUS - Vészhelyzeti bejutási pont + Vészhelyzeti elérési pont Lépőkövek Műszaki vizsgáló állomás Felvonóoszlop @@ -3842,4 +3842,34 @@ Internetcsatlakozás: ügyfeleknek Radartorony GPX-pont + Állampolgári szolgáltatások + nincsenek + vannak + nincs + van + nincs + van + Országrész külképviselete + Emigráns kormány nem akkreditált képviselete + Nem akkreditált összekötő iroda + Tiszteletbeli konzul + Főkonzulátus + Konzuli iroda + Konzuli ügynköség + Konzulátus, élén konzullal + Rezidencia + Apostoli nunciatúra + Állandó küldöttség + Érdekképviseleti részleg + Főbiztosság (brit nemzetközösségi tag nagykövetsége) + Küldöttség + Nagykövetségi részleg + Nagykövetség, élén nagykövettel + Összekötő iroda + Követség + Bevándorlói vízum + Nem bevándorlói vízum + Összekötő iroda + Külképviselet + Konzulátus \ No newline at end of file diff --git a/OsmAnd/res/values-hu/strings.xml b/OsmAnd/res/values-hu/strings.xml index 046855440d..495bb2bca2 100644 --- a/OsmAnd/res/values-hu/strings.xml +++ b/OsmAnd/res/values-hu/strings.xml @@ -1430,7 +1430,7 @@ Hang/videó jegyzetek Online térkép Hang - Megosztási megjegyzés + Jegyzet megosztása Exportálás Turistatérkép-nézet Nyomvonal szakaszok @@ -3917,7 +3917,7 @@ Az OSM-szerkesztési funkciók használatához jelentkezzék be az OAuth segítségével Bejelentkezés OAuth segítségével OpenStreetMap OAuth token törlése - Sikeresen kijelentkezett + Kijelentkezett Kétszakaszos A* útvonaltervezési algoritmus használata A fájl már importálva van az OsmAndba %1$s - %2$s @@ -3953,10 +3953,10 @@ Probléma van az előfizetésével. A fizetési mód kijavítása érdekében kattintson a gombra a Google Play előfizetési beállításaihoz történő ugráshoz. Bejelentkezés Fiók - Fióknév és jelszó használata - Az új vagy módosított szerkesztések feltöltéséhez be kell jelentkeznie. + Bejelentkezés felhasználónévvel és jelszóval + Új vagy módosított szerkesztések feltöltéséhez be kell jelentkeznie. \n -\nBejelentkezhet a biztonságos OAuth-módszerrel vagy használhatja fióknevét és jelszavát. +\nBejelentkezhet a biztonságos OAuth módszerrel vagy használhatja saját felhasználónevét és jelszavát. Bejelentkezés OpenStreetMap-fiókkal Bejelentkezés az OpenStreetMapre Bejelentkezés az OpenStreetMap.org-ra @@ -3966,10 +3966,28 @@ Fénykép hozzáadása Regisztráció az \nOpenPlaceReviews.org oldalon - A fényképeket a OpenPlaceReviews.org nyílt adatprojekt biztosítja. Saját fényképei feltöltéséhez be kell jelentkeznie a weboldalon. + A fényképeket a OpenPlaceReviews.org nyíltadat-projekt biztosítja. Saját fényképei feltöltéséhez be kell jelentkeznie a weboldalon. Új fiók létrehozása Már van fiókom Motorcsónak Kajak Keresési előzmények + Források + Hozzáadás a Mapillaryhez + Hozzáadása az OpenPlaceReviewshoz + Az OsmAnd több forrásból jelenít meg fényképeket: +\nOpenPlaceReviews – POI-fotók; +\nMapillary – utcaszintű képek; +\nWeb / Wikimedia – az OpenStreetMap-adatokban meghatározott POI-fotók. + Hozzávetőleges fájlméret + Jelölje ki a fájlba exportálandó adatokat. + Szükséges az importáláshoz + A készülékén csak %1$s szabad hely van. Szabadítson fel valamennyi helyet, vagy szüntesse meg néhány exportálandó elem kijelölését. + Nincs elég hely + Importálandó csoportok kijelölése. + Importálandó elemek kijelölése. + OSM-jegyzet, POI vagy GPX-nyomvonal feltöltésének teszteléséhez az openstreetmap.org helyett kapcsoljon át a dev.openstreetmap.org-ra. + A dev.openstreetmap.org használata + Nem lehet feltölteni a képet, kérjük, próbálja meg később + Kép kijelölése \ No newline at end of file diff --git a/OsmAnd/res/values-is/strings.xml b/OsmAnd/res/values-is/strings.xml index 00458a4f90..8af3d89837 100644 --- a/OsmAnd/res/values-is/strings.xml +++ b/OsmAnd/res/values-is/strings.xml @@ -1772,7 +1772,7 @@ Hve snemma viltu fá tilkynningu um komu? Ekki nægt vinnsluminni til að birta valið svæði Ónettengdar breytingar - Alltaf nota ónettengdar breytingar. + Ef ónettengdar breytingar eru virkar, þá eru breytingar fyrst vistaðar á tækinu og síðan sendar inn samkvæmt beiðni. Annars gerist þetta jafnóðum. Senda breytingu inn til OSM Ósamstilltar (async) OSM-breytingar: Þú getur sótt eða uppfært %1$s kort. @@ -2164,7 +2164,7 @@ Engar v1.9 leiðareglur Ekki nota leiðareglur sem komu til sögunnar í útgáfu 1.9. Leiðir deilileigubíla - Nafn GPX skráar: + Heiti GPX-skráar: Sýna í korti eftir vistun Mæla vegalengd Geyma skráða ferla í undirmöppum fyrir hvern skráningamánuð (svo sem 2018-01). @@ -2514,7 +2514,7 @@ Veldu skráartegund Öll gögn Sýna lokaða minnispunkta - Birta/fela OSM-minnispunkta á kortinu. + Birta eða fela OSM-minnispunkta á kortinu. GPX - hentar til útflutnings fyrir JOSM eða aðra OSM-ritla. OSC - hentar til útflutnings í OSM. Flytja út sem OSM-minnispunkta, merkisstaði, eða bæði. @@ -3086,7 +3086,7 @@ Veldu notkunarsnið sem eiga að vera sýnileg í forriti. Forritssnið Nota WunderLINQ við stýringu - Brun/svigskíði + Brun og svigskíði Ferðaleiðir á skíðum. Brekkur notaðar fyrir sleða. Leyfa millileiðir @@ -3105,7 +3105,7 @@ Breyttu aðdrætti á kort með skruni músarhjóls upp og niður. Escape fer aftur með þig inn í WunderLINQ forritið. Þú verður að skilgreina a.m.k. eitt atriði í listanum í stillingum flýtiaðgerða Brekkur fyrir svigskíði eða brun og aðgangur að skíðalyftum. - Gönguskíði/norræn fjallaskíði + Gönguskíði og norræn fjallaskíði Leiðir fyrir gönguskíði eða norræn fjallaskíði. Leiðir sem troðnar eru einungis fyrir klassískan stíl en án hluta fyrir skautun. Þetta telur einnig með leiðir sem troðnar eru með minni farartækjum og lausari sporum sem jafnvel eru gerð af skíðagöngufólkinu sjálfu. Kjósa leiðir á þessu erfiðleikastigi, þótt leiðarval um erfiðari eða auðveldari leiðir séu mögulegar ef um stutta búta sé að ræða. @@ -3237,7 +3237,7 @@ Birta kort á læsiskjá á meðan leiðsögn stendur. Stillingar leiðarvals í valda sniðinu \"%1$s\". Tímamörk eftir vöknun - Einingar og snið þeirra + Einingar og snið Útlit Útlit landakorts Útlit korts @@ -3374,7 +3374,7 @@ Upphafspunktur Notað til að áætla komutíma á óþekktum gerðum vega og til takmörkunar á hraða á öllum vegum (gæti breytt leiðarvali) Ferill vistaður - Skráarheiti er autt + Vantar skráarheiti Afturkalla Hnappur til að gera miðju skjásins að upphafsstað. Mun síðan spyrja um áfangastað eða setja í gang útreikning á leiðum. Birta hnútanetkerfi fyrir hjólaleiðir @@ -3582,7 +3582,7 @@ Virkja til að sjá hæðaskyggingar eða brekkur á korti. Þú getur lesið meira um þessa eiginleika á vefnum okkar. Hæðaskygging Brekkur - Birta/fela yfirborð + Birta eða fela yfirborð Fela yfirborð Sýna yfirborð Hnappur til að birta eða fela yfirborðslag á kortinu. @@ -3689,7 +3689,7 @@ Nota tímamörk kerfis fyrir skjá Breyta nettengdum gagnagjafa OsmAnd rekjari - Búa til / breyta merkisstað + Búa til eða breyta merkisstað Geymslusnið Rennur út Flýtiaðgerð @@ -3698,7 +3698,7 @@ Þú getur komist í þessar aðgerðir með því að ýta á \"%1$s\"-hnappinn. Áskrift - OsmAnd Live Alltaf - Birta/fela almenningssamgöngur + Birta eða fela almenningssamgöngur Endurheimta sjálfgefna röð atriða Óstudd tegund Leiðsagnarleiðbeiningar @@ -3707,7 +3707,7 @@ Leiðsagnarsnið Halda áfram OsmAnd + Mapillary - Bæta við / breyta eftirlæti + Bæta við eða breyta eftirlæti Birta almenningssamgöngur Sjálfgefin tímamörk fyrir skjá Hnappur til að birta eða fela almenningssamgöngur á kortinu. @@ -3895,7 +3895,7 @@ Síðast breytt Nafn: Ö – A Nafn: A – Ö - Tákn við upphaf/enda + Tákn við upphaf og enda Forðast gangstéttir Forðast gangstéttir Þróun @@ -3911,12 +3911,12 @@ Útskráning tókst %s GPX-skrár valdar Mun setja GPX-skráningu í bið þegar forritið er drepið (slökkt á því í gegnum skjáinn fyrir nýleg forrit - bakgrunnsvísir OsmAnd hverfur þar með úr tilkynningastiku Android-kerfisins.) - Veldu millibil skráninga í almenna leiðarskráningu (virkjað með viðmótshlutanum fyrir GPX-skráningu á kortinu). + Veldu millibil skráninga í almenna leiðarskráningu (virkjað með viðmótshlutanum \'Skráning ferðar\' á kortinu). Setja skráningu í bið Halda áfram með skráningu • Uppfærðar aðgerðir í skipulagningu leiða: mismunandi leiðsögn á hverjum bút auk slóða \n -\n • Ný útlitsvalmynd fyrir slóðir: val á lit, þykkt, birting stefnuörva, táknmynda við upphaf/endi +\n • Ný útlitsvalmynd fyrir slóðir: val á lit, þykkt, birting stefnuörva, táknmynda við upphaf og endi \n \n • Bættur sýnileiki hjólreiðahnúta. \n @@ -3975,4 +3975,20 @@ OsmAnd notar MGRS, sem er svipað og UTM-snið NATO. Sýsla með áskrift MGRS + \"Opinbert\" þýðir að ferillinn birtist í GPS-ferlunum þínum og á opinberum listum yfir GPS-ferla, þar sem ferilpunktar eru með tímamerkjum á frumsniði. Gögn sem eru sótt í gegnum opinbert GPS API-forritsviðmót vísa ekki í ferlasíðuna þína. Tímamerki ferilpunkta eru ekki tiltæk í gegnum opinbera GPS API-forritsviðmótið og er ekki raðað í tímaröð. + Kayak + Bæta við mynd + \"Auðkennanlegt\" þýðir að ferillinn birtist í GPS-ferlunum þínum og á opinberum listum yfir GPS-ferla, sem þýðir að aðrir notendur geta sútt frumferilinn og tengt þær upplýsingar við notandanafnið þitt. Opinberir ferilpunktar með tímamerkjum sem eru sóttir í gegnum opinbera GPS API-forritsviðmótið vísa í ferlasíðuna þína. + Leitarferill + \"Einka\" þýðir að ferillinn birtist ekki á neinum opinberum listum, en ferilpunktar í ótímasettri röð eru tiltækir í gegnum opinbert GPS API-forritsviðmót án tímamerkja. + Loka OSM-minnispunkti + Ég er nú þegar með notandaaðgang + Skráðu þig á +\nOpenPlaceReviews.org + Búa til nýjan notandaaðgang + Þú getur skráð þig inn með öruggu OAuth-aðferðinni eða notað notandanafn og lykilorð innskráningar. + Vélbátar + Ljósmyndir eru í boði frá opna gagnaverkefninu OpenPlaceReviews.org. Til að geta sent inn myndir þarftu að skrá þig á vefsvæðinu. + Gera athugasemd við OSM-minnispunkt + \"Rekjanlegt\" þýðir að ferillinn birtist ekki á neinum opinberum listum, en meðhöndlaðir ferilpunktar með tímamerkjum úr ferlinum (sem ekki er hægt að tengja beint við þig) munu birtast í gögnum sem eru sótt í gegnum opinbert GPS API-forritsviðmót. \ No newline at end of file diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml index d46ef2e3c1..a8c2b32d25 100644 --- a/OsmAnd/res/values-it/strings.xml +++ b/OsmAnd/res/values-it/strings.xml @@ -3417,7 +3417,7 @@ Note fotografiche Ricalcolo del percorso Nome utente e password - Queste impostazioni del plugin sono globali e si applicano a tutti i profili. + Queste impostazioni del plugin sono globali e si applicano a tutti i profili Modifica di OpenStreetMap È possibile visualizzare tutte le modifiche non caricate o le note OSM in %1$s. I punti caricati non vengono visualizzati in OsmAnd. OSM @@ -3945,14 +3945,56 @@ Sport Emergenza Viaggio - Devi aggiungere almeno due punti. + Devi aggiungere almeno due punti Chiudi la nota OSM Commenta la nota OSM Puoi autenticarti con il metodo sicuro OAuth o utilizzare le tue credenziali. Aggiungi foto Registrati su \nOpenPlaceReviews.org - Le foto sono fornite dal progetto a sorgente aperto OpenPlaceReviews.org. Per contribuire delle tue foto devi registrarti nel sito. + Per contribuire delle altre foto autenticati nel sito del progetto a sorgente aperto OpenPlaceReviews.org. Crea un nuovo account Ho già un account + Cronologia di ricerca + Kayak + Motoscafo + Connettiti a OpenStreetMap + Connettiti a OpenStreetMap.org + Registrati con OpenStreetMap + Devi fare il login per inviare nuove modifiche o dei cambiamenti. +\n +\nPuoi fare login utilizzando il metodo sicuro OAuth o il nomeutente e password. + Usa login e password + Account + Entra + Gestisci la sottoscrizione + C\'è un problema con la tua sottoscrizione. Clicca sul pulsante per andare alle impostazioni di sottoscrizione di Google Play per correggere il tuo metodo di pagamento. + La sottoscrizione di OsmAnd Live è terminata + La sottoscrizione di OsmAnd Live è stata messa in pausa + La sottoscrizione di OsmAnd Live è in sospeso + Cronologia dei marcatori + Invia il file GPX a OpenStreetMap + Immetti le etichette separate dalla virgola. + \"Pubblico\" significa che la traccia è visualizzata pubblicamente nelle tue tracce GPS, nelle liste pubbliche di tracce GPS con le informazioni temporali in forma grezza. I dati forniti attraverso le API non conducono alla tua pagina delle tracce. Le informazioni temporali dei punti traccia non sono disponibili attraverso le API GPS pubbliche, e i punti della traccia non sono ordinati cronologicamente. + \"Privato\" significa che la traccia non è visualizzabile in alcuna lista pubblica ma i suoi punti, in ordine non cronologico, sono disponibili attraverso le API GPS senza le informazioni temporali. + \"Identificabile\" significa che la traccia è visualizzabile nelle Mie tracce GPS e nelle liste pubbliche, es. gli altri utenti potranno scaricare la traccia grezza e associarla con il tuo nome utente. I punti della traccia, con le loro informazioni temporali, saranno riconducibili, attraverso le API GPS, alla tua traccia originale. + \"Tracciabile\" significa che la traccia non è visualizzabile in alcuna lista pubblica, ma solo i suoi punti, processati, con le informazioni temporali (che non possono essere direttamente associati a te) attraverso le API GPS pubbliche. + Aggiungi a Mapillary + Aggiungi a OpenPlaceReviews + OsmAnd mostra foto da più sorgenti: +\nOpenPlaceReviews - foto PDI; +\nMapillary - immagini stradali; +\nWeb / Wikimedia - foto PDI OpenStreetMap. + Risorse + Dimesione approssimativa del file + Seleziona i dati da esportare nel file. + Necessario per l\'importazione + Il tuo dispositivo ha solo %1$s liberi. Libera dello spazio o deseleziona alcune voci da esportare. + Non c\'è abbastanza spazio + Seleziona i gruppi da importare. + Seleziona gli oggetti da importare. + Per testare l\'upload di Note OSM / PDI / GPX, invece di utilizzare invece di openstreetmap.org spostati su dev.openstreetmap.org. + Utilizza dev.openstreetmap.org + Impossibile caricare l\'immagine, riprovare in seguito + Scegli la foto \ No newline at end of file diff --git a/OsmAnd/res/values-iw/strings.xml b/OsmAnd/res/values-iw/strings.xml index 81122d590f..179d8ee142 100644 --- a/OsmAnd/res/values-iw/strings.xml +++ b/OsmAnd/res/values-iw/strings.xml @@ -3930,7 +3930,7 @@ יש להיכנס עם OAuth כדי להשתמש ביכולות של osmedit להיכנס דרך OAuth למחוק את אסימון ה־OAuth של OpenStreetMap - היציאה הצליחה + יצאת הקובץ כבר ייובא אל OsmAnd להשתמש באלגוריתם חישוב מסלול דו־שלבי A*‎ לנהיגה ברכבי שלג עם דרכים ומסלולים יעודיים. @@ -3952,18 +3952,18 @@ MGRS MGRS עליך להוסיף שתי נקודות לפחות - כניסה ל־OpenStreetMap - כניסה ל־OpenStreetMap.org - כניסה עם OpenStreetMap - להשתמש בשם כניסה וססמה + כניסה אל OpenStreetMap + כניסה אל OpenStreetMap.org + רישום עם OpenStreetMap + להיכנס עם שם כניסה וססמה חשבון - כניסה + שם כניסה ניהול מינוי תוקף המינוי ל־OsmAnd Live פג המינוי ל־OsmAnd Live הושהה - עליך להיכנס כדי להעלות דברים חדשים או כאלו ששינית. + עליך להיכנס כדי להעלות שינויים חדשים או כאלו שנערכו. \n -\nניתן להיכנס בשיטת OAuth המאובטחת או להשתמש בשם הכניסה והססמה שלך. +\nניתן להיכנס בשיטת OAuth המאובטחת או באמצעות שם הכניסה והססמה שלך. יש בעיה עם המינוי שלך. יש ללחוץ על הכפתור כדי לגשת להגדרות המינוי של Google Play ולתקן את שיטת התשלום שלך. המינוי ל־OsmAnd Live מוחזק היסטוריית סמנים @@ -3976,10 +3976,29 @@ הוספת תמונה יש להירשם בכתובת \nOpenPlaceReviews.org - תמונות מסופקות על ידי מיזם הנתונים הפתוחים OpenPlaceReviews.org. כדי להעלות את התמונות שלך עליך להירשם לאתר. + התמונות מסופקות על ידי מיזם הנתונים הפתוחים OpenPlaceReviews.org. כדי להעלות את התמונות שלך עליך להירשם באתר. יצירת חשבון חדש כבר יש לי חשבון היסטוריית חיפוש קיאק סירת מנוע + + משאבים + גודל קובץ משוערך + נא לבחור את הנתונים שייוצאו לקובץ. + נדרש לייבוא + במכשיר שלך יש רק %1$s פנויים. נא לפנות מקום או לבטל כמה מהפריטים לייצוא. + אין מספיק מקום + הוספה ל־Mapillary + הוספה ל־OpenPlaceReviews + OsmAnd מציג תמונות ממגוון מקורות: +\nOpenPlaceReviews - תמונות של נקודות עניין; +\nMapillary - תמונות ברמת הרחוב; +\nאינטרנט / ויקימדיה - תמונות נקודות עניין שמצוינות בנתונים של OpenStreetMap. + נא לבחור קבוצות שייובאו. + נא לבחור פריטים שייובאו. + לעבור להשתמש ב־dev.openstreetmap.org במקום ב־openstreetmap.org כדי לבדוק העלאות של הערות OSM / נקודות עניין / GPX. + להשתמש ב־dev.openstreetmap.org + לא ניתן להעלות תמונה, נא לנסות שוב מאוחר יותר + בחירת תמונה \ No newline at end of file diff --git a/OsmAnd/res/values-lt/strings.xml b/OsmAnd/res/values-lt/strings.xml index 36989898e7..049ac26e8c 100644 --- a/OsmAnd/res/values-lt/strings.xml +++ b/OsmAnd/res/values-lt/strings.xml @@ -2777,4 +2777,7 @@ Tai yra puikus būdas paremti OsmAnd ir OSM, jei jie jums patinka. Pridėtas taškas nebus matomas žemėlapyje, nes pasirinkta grupė yra paslėpta, ją galite rasti \"%s\". Pasirinkite intervalą nuo kurio taškas su atstumu ar laiku bus pavaizduojamas ekrane ant trasos. Pasirinkite norima dalinimo variantą: pagal laiką arba pagal atstumą. + Pridėti nuotrauką + Sukurti naują paskyrą + Aš jau turiu paskyrą \ No newline at end of file diff --git a/OsmAnd/res/values-lv/strings.xml b/OsmAnd/res/values-lv/strings.xml index e505fe8b91..7e38654e34 100644 --- a/OsmAnd/res/values-lv/strings.xml +++ b/OsmAnd/res/values-lv/strings.xml @@ -3212,9 +3212,9 @@ No Afganistānas līdz Zimbabvei, no Austrālijas līdz ASV, Argentīna, Brazīl Maršruta pārrēķināšana Paziņošana Lietotāja vārds un parole - Šie iestatījumi darbosies visos profilos. + Šie iestatījumi ir globāli un darbosies visos profilos OSM rediģēšana - Skatiet vēl neaugšupielādētos labojumus vai OSM kļūdas %1$s mapē. Augšupielādētie punkti vairs netiks rādīti. + Skatiet neaugšupielādētos labojumus vai OSM kļūdas %1$s mapē. Augšupielādētie punkti vairs netiek rādīti OsmAnd lietotnē. OSM Ikona, kas redzama naviģējot vai pārvietojoties. Ikona, kas redzama pārtraukumos. @@ -3278,13 +3278,13 @@ No Afganistānas līdz Zimbabvei, no Austrālijas līdz ASV, Argentīna, Brazīl Ārkārtas Ceļošana Nepieciešams pievienot vismaz divus punktus - Ieiet OpenStreetMap - Ieiet OpenStreetMap.org + Pierakstīties OpenStreetMap + Pierakstīties OpenStreetMap.org Pierakstīties ar OpenStreetMap Lai sūtītu labojumus vai jaunus datus, ir nepieciešams pierakstīties. \n -\nJūs varat pierakstīties, lietojot drošo OAuth metodi vai ar savu lietotāja vārdu un paroli. - Lietot pierakstīšanās datus +\nJūs varat pierakstīties, lietojot drošo OAuth vai ar savu lietotāja vārdu un paroli. + Pierakstīties ar lietotāja vādu un paroli Konts Lietotājs Pārvaldīt abonomentu @@ -3297,10 +3297,71 @@ No Afganistānas līdz Zimbabvei, no Austrālijas līdz ASV, Argentīna, Brazīl Ievadiet tagus, atdalītus ar komatu. Aizvērt OSM Note Komentēt OSM Note - Jūs varat ielogoties lietojot drošo OAuth metodi vai savu lietotāja vārdu un paroli. + Ielogojieties ar drošo OAuth metodi vai savu lietotāja vārdu un paroli. Pievienot foto Reģistrēties \nOpenPlaceReviews.org - Fotogrāfijas tiek piegādātas no atvērtā koda projekta OpenPlaceReviews.org. Lai pievienotu savas fotogrāfijas, nepieciešams reģistrēties šajā interneta vietnē. + Fotogrāfijas nodrošina atvērtā koda projekts OpenPlaceReviews.org. Lai augšupielādētu savas fotogrāfijas, pierakstieties interneta vietnē. Izveidot jaunu kontu + Simboli + Sports + \"Privāts\" nozīmē, ka trase neparādīsies nevienā publiskā sarakstā, bet trases punkti nehronoloģiskā secībā būs pieejami caur publisko GPS API bez laika atzīmēm. + \"Identificējams\" nozīmē, ka trase būs redzama jūsu GPS trasēs un publiskajos GPS trašu sarakstos, t.i. citi lietotāji varēs lejupielādēt trasi un asociēt to ar jūsu vārdu. Publiskie trases punktu dati ar laika atzīmēm no GPS API caur trackpoints API dos referenci uz jūsu oriģinālo trases lapu. + \"Izsekojams\" nozīmē, ka pati trase neparādās publiskajos sarakstos, bet tikai apstrādātie trackpointi ar laika atzīmēm (nevar tikt asociēti konkrēti ar jums) caur lejupielādēm no publiskā GPS API. + Man jau ir konts + Meklēšanas vēsture + Kajaks + Motorlaiva + Pievienot Mapillary + Pievienot OpenPlaceReviews + OsmAnd rāda attēlus no dažādiem avotiem: +\nOpenPlaceReviews - POI bildes; +\nMapillary - ielas līmeņa attēli; +\nWeb / Wikimedia - POI bildes no OpenStreetMap datiem. + Resursi + Aptuvenais faila izmērs + Izvēlieties datus eksportēšanai failā. + Nepieciešams importam + Ierīcē ir tikai %1$s brīvās vietas. Lūdzu atbrīvojiet vietu vai izvēlieties mazāk detaļu eksportam. + Nepietiek brīvās vietas + Visi iepriekšējie segmenti tiks pārrēķināti, lietojot izvēlēto profilu. + Atvērt saglabātu treku + Saglabāts + Nepieciešami vismaz divi punkti. + Atkārtot + Labots + Vārdi: Z - A + Vārdi: A -Z + Starta un finiša ikonas + Paldies par \'Contour lines\' pirkumu + Izvairīties no gājēju celiņiem + Izvairīties no gājēju celiņiem + Izstrāde + OsmAnd Live dati + OsmAnd Live dati + Divu-fāžu maršrutēšana auto navigācijai. + Pārslēgties uz Java (drošs) publiskā transporta maršruta aprēķināšanai + Ielogoties ar OAuth, lai lietotu osmedit iespējas + Ielogoties ar OAuth + Notīrīt OpenStreetMap OAuth token + Izlogošanās veiksmīga + Fails jau ir importēts + Lietot 2-fāžu A* maršrutēšanas algoritmu + Grafika + %1$s dati ir pieejami ceļiem, ir nepieciešams pārrēķināt maršrutu, lietojot \"maršrutēt caur punktiem\". + Gaidiet maršruta pārrēķināšanu. +\nGrafika būs redzama pēc brīža. + Vietējās kartes + %1$s — %2$s + Sprauga + Speciālais + Transports + Serviss + \"Publisks\" nozīmē, ka trase ir redzama jūsu GPS trasēs un GPS trašu publiskajos sarakstos, un publisko trašu sarakstos ar laika atzīmēm pamatformā. Dati caur API neatspoguļo jūsu trases lapu. Trašu punktu laika atzīmes nav pieejams caur publisko GPS API un trašu punkti nav hronoloģiski sakārtoti. + Nevar augšupielādēt bildi, lūdzu mēģiniet vēlreiz + Izvēlieties bildi + Izvēlieties grupas, ko importēt. + Izvēlieties lietas, ko importēt. + Lietot dev.openstreetmap.org nevis openstreetmap.org OSM piezīmju/ POI / GPX augšuielādei un testēšanai. + Lietot dev.openstreetmap.org \ No newline at end of file diff --git a/OsmAnd/res/values-nb/strings.xml b/OsmAnd/res/values-nb/strings.xml index 8ccc84ede3..c2f36f8a9e 100644 --- a/OsmAnd/res/values-nb/strings.xml +++ b/OsmAnd/res/values-nb/strings.xml @@ -1692,7 +1692,7 @@ \n \n OsmAnd utvikles aktivt, og prosjektet vårt og dets videre framdrift avhenger av finansielle bidrag for å drive utviklingen og testingen av nye funksjoner. Overvei å kjøpe OsmAnd+ eller støtte spesifikke nye funksjoner eller bidra med en generell donasjon på https://osmand.net. Last opp ditt OSM-notat anonymt eller ved å bruke din profil hos OpenStreetMap.org. - Du har ingen sporfiler ennå + Du har ingen sporfiler enda Du kan også legge til sporfiler i mappen Legg til flere… Skru på hurtigopptak @@ -1792,7 +1792,7 @@ Start nettbasert sporing Stopp nettbasert sporing Fant ikke noe. Hvis du ikke finner din region, kan du lage den selv (se https://osmand.net). - Spesifiser først en GPX-fil med et langt trykk. + Spesifiser en GPX-fil med et langt trykk først. Oppdelingsintervall Nedstigning/stigning: %1$s Tidsrom: %1$s @@ -3887,7 +3887,7 @@ Nødsfall Reise Du må legge til minst to punkter. - Sporbar betyr at sporet ikke vil vises i offentlige lister, men punkter fra det vil fremdeles ikke være tilgjengelige gjennom det offentlige GPS-API-et med tidsstempel. Andre brukere vil kun ha mulighet til å laste ned behandlede punkter fra ditt spor, noe som ikke kan tilknyttes deg direkte. + \"Sporbar\" betyr at sporet ikke vil vises i offentlige lister, men bearbeidede sporpunkter med tidsstempel (som ikke direkte kan knyttes til deg) vil være tilgjengelig gjennom nedlastinger fra det offentlige GPS-API-et. Logg inn med OpenStreetMap Bruk innlogging og passord Konto @@ -3919,4 +3919,8 @@ Søkehistorikk Kajakk Motorbåt + Velg bilde + Legg til i Mapillary + Legg til i OpenPlaceReviews + Bruk dev.openstreetmap.org \ No newline at end of file diff --git a/OsmAnd/res/values-pl/strings.xml b/OsmAnd/res/values-pl/strings.xml index 5a3ad96826..2d58273576 100644 --- a/OsmAnd/res/values-pl/strings.xml +++ b/OsmAnd/res/values-pl/strings.xml @@ -441,7 +441,7 @@ Automatyczne rejestrowanie śladu podczas nawigacji Uaktualnij mapę Wczytaj ponownie kafelki - Potrzebny do zgłaszania do openstreetmap.org. + Potrzebne do przysyłania zmian do serwisu openstreetmap.org. Nazwa użytkownika OSM Cel Dodaj do ulubionych @@ -1922,7 +1922,7 @@ Subskrypcja umożliwia cogodzinne aktualizacje wszystkich map na całym świecie. \n Część dochodów wraca do społeczności OSM i jest wypłacana za każdy wkład OSM. \n Jeśli kochasz OsmAnd i OSM i chcesz je wspierać i wspierać, jest to idealny sposób, aby to zrobić. - Nazwa pliku zawiera niedozwolony znak + Niedozwolony znak w nazwie pliku Domyślny kolor Wybierz kategorię Proszę wprowadzić kategorię @@ -2526,7 +2526,7 @@ Dodaje cel pośredni Dodaje pierwszy cel pośredni Wyświetl zamknięte uwagi - Pokaż/ukryj uwagi OSM na mapie. + Pokaż lub ukryj uwagi OSM na mapie. GPX - odpowiedni do eksportowania danych do JOSM i innych edytorów OSM. OSC - odpowiedni do eksportowania danych do OSM. Plik GPX @@ -3087,7 +3087,7 @@ Użyj WunderLINQ do kontroli Dodaj co najmniej jeden element do listy w ustawieniach \"Szybkiej Akcji\" Stoki narciarskie do narciarstwa alpejskiego i zjazdowego oraz dostęp do wyciągów narciarskich. - Narty biegowe/nordic ski + Biegi narciarskie i narciarstwo klasyczne Trasy do narciarstwa klasycznego lub biegowego. Turystyka narciarska Trasy wycieczek narciarskich. @@ -3570,7 +3570,7 @@ Przycisk do wyświetlania lub ukrywania warstwy terenu na mapie. Pokaż teren Ukryj teren - Pokaż / ukryj teren + Pokaż lub ukryj teren Nachylenie Włącz, aby wyświetlić cieniowanie wzniesień lub stoków. Możesz przeczytać więcej o tego rodzaju mapach na naszej stronie. Legenda @@ -3700,9 +3700,9 @@ Powrót do edycji Ukryj transport publiczny Pokaż transport publiczny - Pokaż/ukryj transport publiczny - Utwórz / Edytuj użyteczne miejsce - Dodaj / Edytuj Ulubione + Pokaż lub ukryj transport publiczny + Utwórz lub edytuj użyteczne miejsce + Dodaj lub edytuj ulubione miejsce Przycisk akcji przełącza między wybranymi profilami. Dodaj profil Zmiana profilu aplikacji @@ -3910,7 +3910,7 @@ Nazwa: Z – A Nazwa: A – Z Co nowego - Ikony start/koniec + Ikony startu i końca 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. @@ -3927,10 +3927,10 @@ Dwufazowe wyznaczanie tras do nawigacji samochodowej. Rozwój rodzimego transportu publicznego Przejdź do (bezpiecznego) obliczania tras transportu publicznego w języku Java - Wykonaj logowanie OAuth, aby korzystać z funkcji osmedit + Zaloguj się za pomocą protokołu OAuth, aby korzystać z funkcji osmedit Zaloguj się przez OAuth Wyczyść token OpenStreetMap OAuth - Wylogowanie powiodło się + Wylogowano Plik jest już zaimportowany do OsmAnd %1$s — %2$s MGRS @@ -3958,14 +3958,14 @@ Musisz dodać co najmniej dwa punkty Wystąpił problem z Twoją subskrypcją. Kliknij przycisk, aby przejść do ustawień subskrypcji Google Play i naprawić metodę płatności. Subskrypcja OsmAnd Live jest wstrzymana - Login + Nazwa użytkownika Zaloguj się do OpenStreetMap Zaloguj się do OpenStreetMap.org Zaloguj się za pomocą OpenStreetMap - Musisz się zalogować, aby przesłać nowe lub zmodyfikowane zmiany. + Zaloguj się, aby przesłać nowe lub zmodyfikowane zmiany, \n -\nMożesz zalogować się za pomocą bezpiecznej metody autoryzacji OAuth lub użyć swojego loginu i hasła. - Użyj loginu i hasła +\nza pomocą protokołu OAuth lub nazwy użytkownika i hasła. + Zaloguj się za pomocą nazwy użytkownika i hasła Konto Zamknij uwagę OSM Skomentuj uwagę OSM @@ -3973,11 +3973,30 @@ Wyślij plik GPX do OpenStreetMap Wpisz tagi oddzielone przecinkami. Możliwość śledzenia oznacza, że ślad nie pojawi się na żadnej publicznej liście, ale punkty śledzenia będą nadal dostępne za pośrednictwem publicznego API GPS ze znacznikami czasu. Inni użytkownicy będą mogli pobrać tylko te przetworzone punkty śledzenia z Twojego śladu, których nie można powiązać bezpośrednio z Tobą. - Możesz zalogować się przy użyciu bezpiecznej metody OAuth lub użyć swojego loginu i hasła. + Zaloguj się przy użyciu bezpiecznej metody autoryzacji OAuth lub użyj swojej nazwy użytkownika i hasła. Dodaj zdjęcie Zarejestruj się w \nOpenPlaceReviews.org - Zdjęcia są dostarczane przez projekt OpenPlaceReviews.org. Aby przesłać swoje zdjęcia należy zarejestrować się na stronie. + Zaloguj się na stronie projektu otwartych danych OpenPlaceReviews.org, aby przesłać jeszcze więcej zdjęć. Utwórz nowe konto Mam już konto + Wybierz grupy, które zostaną zaimportowane. + Wybierz elementy, które zostaną zaimportowane. + Przełącz na dev.openstreetmap.org zamiast openstreetmap.org do testowania przesyłania uwag OSM / użytecznych miejsc / GPX. + OsmAnd pokazuje zdjęcia z kilku źródeł: +\nOpenPlaceReviews - zdjęcia punktów użyteczności; +\nMapillary - zdjęcia z poziomu ulicy; +\nWeb / Wikimedia - zdjęcia określonych punktów użyteczności w danych OpenStreetMap. + Zasoby + Przybliżony rozmiar pliku + Wybierz dane do wyeksportowania do pliku. + Potrzebne do importu + Twoje urządzenie ma tylko %1$s wolnego miejsca. Zwolnij trochę miejsca lub odznacz niektóre elementy do wyeksportowania. + Nie ma wystarczającej ilości miejsca + Skorzystaj z dev.openstreetmap.org + Historia wyszukiwania + Kajak + Motorówka + Dodaj do Mapillary + Dodaj do OpenPlaceReviews \ No newline at end of file diff --git a/OsmAnd/res/values-pt-rBR/phrases.xml b/OsmAnd/res/values-pt-rBR/phrases.xml index cde5e0611b..a52a317b33 100644 --- a/OsmAnd/res/values-pt-rBR/phrases.xml +++ b/OsmAnd/res/values-pt-rBR/phrases.xml @@ -3850,4 +3850,34 @@ Torre de radar Tapume Terraço + Não + Sim + Não + Sim + Não + Sim + Subnacional + Escritório de representação + Escritório + Consul honorário + Consulado Geral + Escritório consular + Agência consular + Chefiado por um cônsul + Residência + Nunciatura + Missão + Seção de interesses + Alto comissariado + Delegação + Seção + Chefiado por um embaixador + Ligação + Embaixada + Serviços ao cidadão + Vistos de imigrante + Vistos de não imigrante + Ligação + Consulado + Embaixada \ No newline at end of file diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml index 802205f9e0..aa23de4b3a 100644 --- a/OsmAnd/res/values-pt-rBR/strings.xml +++ b/OsmAnd/res/values-pt-rBR/strings.xml @@ -2389,7 +2389,7 @@ \n O plugin de mapas de ski Skiing OsmAnd permite que você veja pistas de ski com nível de complexidade e algumas informações adicionais, como localização de elevadores e outras facilidades. Buffer de tempo para rastreamento on-line O nome contém muitas letras maiúsculas. Continuar\? - O nome do arquivo contém caracteres ilegais + Caráter ilegal no nome do arquivo Ação rápida Ação %d Tela %d @@ -2551,7 +2551,7 @@ \n Laociano Mostrar notas encerradas - Mostrar/ocultar notas OSM no mapa. + Mostrar ou ocultar notas OSM no mapa. Arquivo GPX Arquivo OSC Selecione o tipo de arquivo @@ -3078,9 +3078,9 @@ Altere o zoom do mapa rolando a roda para cima e para baixo. Escape retorna para o aplicativo WunderLINQ. Use o WunderLINQ para controle Adicionar ao menos um item à lista nas configurações de \'Ação rápida\' - Esqui alpino/de declínio + Esqui alpino e downhill Pistas de esqui alpino ou de declínio e acesso a teleféricos. - Cross country/esqui nórdico + Cross country e esqui nórdico Trilhas para esqui nórdico ou cross-country. Turismo de esqui Rotas para passeios de esqui. @@ -3359,7 +3359,7 @@ Ponto de partida Estima a hora de chegada de tipos de estradas desconhecidas e limita a velocidade de todas as estradas (pode afetar o roteamento) Trilha salva - O nome do arquivo está vazio + Nome de arquivo vazio Reverter Um botão para fazer com que a tela centralize o ponto de partida. Em seguida, solicitará para definir o destino ou acionar o cálculo da rota. Mostrar os nós da rede de ciclovias @@ -3569,7 +3569,7 @@ Sombras de relevo %1$s de %2$s Encostas - Mostrar / ocultar terreno + Mostrar ou ocultar terreno Ocultar terreno Mostrar terreno Um botão para mostrar ou ocultar a camada do terreno no mapa. @@ -3686,11 +3686,11 @@ Você pode acessar essas ações tocando no botão “%1$s”. Ocultar transporte público Mostrar transporte público - Mostrar/ocultar transporte público + Mostrar ou ocultar transporte público Botão que mostra ou oculta o transporte público no mapa. - Criar / Editar POI + Criar ou editar POI Posições de estacionamento - Adicionar / Editar favorito + Adicionar ou editar favoritos Restaurar ordem de itens padrão Voltar à edição Retomar @@ -3867,7 +3867,7 @@ Nome do arquivo %s arquivos de trilha selecionados Pausará o registro de rastreamento quando o aplicativo for encerrado (por meio de aplicativos recentes). (A indicação de uso em segundo plano do OsmAnd desaparece da barra de notificação do Android.) - Especifique o intervalo de registro para a gravação geral da trilha (habilitado por meio do widget Gravação de viagem no mapa). + Especifique o intervalo de registro para a gravação geral da trilha (ligado por meio do widget de \'gravação de viagem\' no mapa). Pausar gravação de viagem Retomar a gravação da viagem Padrão do sistema @@ -3883,7 +3883,7 @@ Refazer "• Função de planejamento de rota atualizada: permite o uso de diferentes tipos de navegação por segmento e a inclusão de trilhas \n -\n • Novo menu de aparência para trilhas: selecione cor, espessura, setas de direção de exibição, ícones de início / término +\n • Novo menu de aparência para trilhas: selecione cor, espessura, setas de direção de exibição, ícones de início e término \n \n • Melhor visibilidade dos nós da bicicleta. \n @@ -3899,7 +3899,7 @@ Última modificação Nome: Z – A Nome: A – Z - Ícones de início/término + Ícones de início e término Obrigado por adquirir \'curvas de nível\' Assinatura cobrada por período selecionado. Cancele no AppGallery a qualquer momento. O pagamento será cobrado em sua conta AppGallery na confirmação da compra. @@ -3917,10 +3917,10 @@ Desenvolvimento de transporte público nativo Mudar para cálculo de roteamento de transporte público em Java (seguro) O que há de novo - Entre no OAuth para usar os recursos de edição do osm + Entrar com OAuth para usar os recursos osmedit Entrar via OAuth Limpar token do OpenStreetMap OAuth - Saída bem sucedida + Desconectado O arquivo já foi importado para OsmAnd Use o algoritmo de roteamento 2-phase A * Para dirigir em motos de neve com estradas e trilhas exclusivas. @@ -3948,29 +3948,50 @@ A assinatura do OsmAnd Live foi pausada A assinatura do OsmAnd Live está em espera Diferença - Entrar para OpenStreetMap + Entrar com OpenStreetMap Entrar com OpenStreetMap.org - Você precisa entrar para enviar alterações novas ou modificadas. + Você precisaentrar para carregar de alterações novas ou modificadas. \n -\nVocê pode entrar usando o método OAuth seguro ou usar sua entrada e senha. - Usar a entrada e senha +\nVocê pode fazer login usando o método OAuth seguro ou usar sua entrada e senha. + Usar entrada e senha Conta Entrar Entrar com o OpenStreetMap Histórico de marcadores Enviar arquivo GPX para OpenStreetMap Insira as etiquetas separadas por vírgula. - Público significa que o traçado será mostrado publicamente em Seus traços de GPS e em listas públicas de traços de GPS. Os dados fornecidos por meio da API não fazem referência à sua página de rastreamento. Os carimbos de data/hora dos pontos de rastreamento não estão disponíveis por meio da API GPS pública e os pontos não são ordenados cronologicamente. No entanto, outros usuários ainda podem fazer o download do rastreamento bruto da lista pública de rastreamento e de quaisquer carimbos de data/hora contidos nela. - Privado significa que o rastreamento não aparecerá em nenhuma lista pública, mas os pontos de trilha dele ainda estarão disponíveis por meio da API GPS pública sem carimbos de data/hora, mas não serão ordenados cronologicamente. - Identificável significa que o traço será mostrado publicamente em Seus traços de GPS e em listas públicas de traços de GPS, ou seja, outros usuários poderão fazer download do traço bruto e associá-lo ao seu nome de usuário. Os dados fornecidos por meio da API de pontos de trilha farão referência à sua página de rastreamento original. Os carimbos de data/hora dos pontos de rastreamento estão disponíveis por meio da API GPS pública. - Rastreável significa que o rastreamento não aparecerá em nenhuma lista pública, mas os pontos de trilha dele ainda estarão disponíveis por meio da API GPS pública com carimbos de data/hora. Outros usuários só poderão baixar pontos de trilha processados de seu trace, que não podem ser associados a você diretamente. + \"Público\" significa que o traçado é mostrado publicamente em seus traços GPS e em listagens públicas de traços GPS e na lista pública de traços com carimbos de data/hora em formato bruto. Os dados fornecidos por meio da API não fazem referência à sua página de rastreamento. Os carimbos de data/hora do ponto de rastreamento não estão disponíveis por meio da API GPS pública e os pontos de rastreamento não são ordenados cronologicamente. + \"Privado\" significa que o rastreamento não aparece em nenhuma listagem pública, mas os pontos de trilha dele em ordem não sincronizada estão disponíveis por meio da API GPS pública sem carimbos de data/hora. + \"Identificável\" significa que o traço será mostrado publicamente em Seus traços de GPS e em listas públicas de traços de GPS, ou seja, outros usuários poderão fazer download do traço bruto e associá-lo ao seu nome de usuário. Os dados de pontos de rastreamento com carimbo de data/hora públicos da API GPS servidos por meio da API de pontos de rastreamento farão referência à sua página de rastreamento original. + \"Rastreável\" significa que o rastreamento não aparece em nenhuma listagem pública, mas os pontos de trilha processados com carimbos de data/hora (que não podem ser associados a você diretamente) são feitos por meio de downloads da API GPS pública. Fechar nota do OSM Comentário de nota do OSM Você pode entrar usando o método OAuth seguro ou usar sua entrada e senha. Adicionar foto Cadastre-se em \nOpenPlaceReviews.org - As fotos são fornecidas pelo projeto de dados abertos do OpenPlaceReviews.org. Para carregar suas fotos você precisa se inscrever no site. + As fotos são fornecidas pelo projeto de dados abertos OpenPlaceReviews.org. Para carregar suas fotos você precisa se inscrever no site. Criar nova conta Eu já tenho uma conta + Histórico de busca + Caiaque + Lancha + Adicionar ao Mapillary + Adicionar ao OpenPlaceReviews + OsmAnd mostra fotos de várias fontes: +\nOpenPlaceReviews - fotos de POI; +\nMapillary - imagens de nível da rua; +\nWeb / Wikimedia - fotos de POI especificadas nos dados do OpenStreetMap. + Recursos + Tamanho aproximado do arquivo + Selecione os dados a serem exportados para o arquivo. + Necessário para importação + Seu dispositivo tem apenas %1$s livre. Libere espaço ou desmarque alguns itens para exportar. + Não há espaço suficiente + Selecione os grupos que serão importados. + Selecione os itens que serão importados. + Mudar para usar dev.openstreetmap.org em vez de openstreetmap.org para testar o carregamento de notas OSM / POI / GPX. + Usar dev.openstreetmap.org + Não é possível carregar a imagem, por favor, tente novamente mais tarde + Selecione a foto \ No newline at end of file diff --git a/OsmAnd/res/values-pt/phrases.xml b/OsmAnd/res/values-pt/phrases.xml index eb04e28ff5..0795fa347c 100644 --- a/OsmAnd/res/values-pt/phrases.xml +++ b/OsmAnd/res/values-pt/phrases.xml @@ -3835,4 +3835,34 @@ Ponto GPX Torre de radar Área de repouso + Não + Sim + Não + Sim + Não + Sim + Subnacional + Escritório de representação + Escritório + Cônsul honorário + Consulado-geral + Escritório consular + Agência consular + Liderado por um cônsul + Residência + Nunciatura + Missão + Secção de interesses + Alta comissão + Delegação + Secção + Liderado por um embaixador + Ligação + Embaixada + Serviços ao cidadão + Vistos de imigrantes + Vistos de não-imigrantes + Ligação + Consulado + Embaixada \ No newline at end of file diff --git a/OsmAnd/res/values-pt/strings.xml b/OsmAnd/res/values-pt/strings.xml index 0c7ff7cbac..cd4664a6dd 100644 --- a/OsmAnd/res/values-pt/strings.xml +++ b/OsmAnd/res/values-pt/strings.xml @@ -3468,7 +3468,7 @@ Perfis Ações rápidas Nada selecionado - Tipos de POI + Tipos de PDI A preparar Ângulo mínimo entre minha localização e rota Segmento reto adicional entre minha localização e a rota calculada será exibida até que a rota seja recalculada @@ -3973,11 +3973,29 @@ Rastreável significa que o rastreamento não aparecerá em nenhuma lista pública, mas os pontos de rastreamento a partir dele ainda estarão disponíveis através da API pública do GPS com carimbos de tempo. Outros utilizadores só poderão descarregar pontos de rastreamento processados do seu rastreamento que não podem ser associados diretamente a si. Fechar nota do OSM Comentário de nota do OSM - Pode entrar a usar o método seguro OAuth ou usar o seu login e palavra-passe. + Faça login a usar o método seguro OAuth ou use o seu nome de utilizador e a palavra-passe. Adicionar fotos Cadastre-se em \nOpenPlaceReviews.org - As fotos são fornecidas pelo projeto de dados abertos OpenPlaceReviews.org. Para enviar as suas fotos precisa cadastrar-se no site. + Faça login no site do projeto de dados abertos OpenPlaceReviews.org para enviar ainda mais fotos. Criar uma conta Já tenho uma conta + Histórico de pesquisa + Caiaque + Barco a motor + Recursos + Tamanho aproximado do ficheiro + Selecione os dados a serem exportados para o ficheiro. + Necessário para a importação + O seu aparelho só tem %1$s livre. Por favor, libere algum espaço ou desmarque alguns itens para exportar. + Não há espaço suficiente + Adicionar ao Mapillary + Adicionar ao OpenPlaceReviews + OsmAnd mostra fotos de várias fontes: +\nOpenPlaceReviews - fotos de POI; +\nMapillary - imagens ao nível da rua; +\nWeb / Wikimedia - fotos de POI especificadas nos dados do OpenStreetMap. + Seleccionar os grupos que serão importados. + Seleccionar os objectos que serão importados. + Utilizar dev.openstreetmap.org \ No newline at end of file diff --git a/OsmAnd/res/values-ru/phrases.xml b/OsmAnd/res/values-ru/phrases.xml index ff47fdaea2..fb1dc5e65d 100644 --- a/OsmAnd/res/values-ru/phrases.xml +++ b/OsmAnd/res/values-ru/phrases.xml @@ -3836,4 +3836,32 @@ Навесы Точка GPX Радиолокационная вышка + Придорожная стоянка + На крыше + Нет + Да + Нет + Да + Нет + Да + Представительство + Офис + Почетный консул + Генеральное консульство + Консульский офис + Во главе с консулом + Резиденция + Нунциатура + Миссия + Верховный комиссариат + Делегация + Филиал + Во главе с послом + Связь + Посольство + Гражданские услуги + Иммиграционные визы + Неиммиграционные визы + Связь + Посольство \ No newline at end of file diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index 66894bb368..1ae090253b 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -398,7 +398,7 @@ Флуоресцентные цвета Использовать флуоресцентные цвета для отображения треков и маршрутов. Локальное редактирование - Всегда использовать редактирование на устройстве. + Если используется редактирование на устройстве, то изменения будут сохранены локально и загружены на сервер только по запросу, иначе они будут загружаться немедленно. Изменение POI в приложении не меняет POI загруженные из интернета, однако все изменения сохраняются в локальный файл на устройстве. Отправка… {0} POI/заметок отправлено @@ -3107,7 +3107,7 @@ Режим пользователя, полученный из: %s Повторяющееся имя BRouter (локально) - Горнолыжные спуски + Альпийские и горные лыжи Склоны для катания и спуска на горных лыжах и доступ к подъёмникам. Лыжные туры Сани @@ -3168,7 +3168,7 @@ Пользовательский профиль навигации Специальная навигация Сторонняя навигация - Лыжные гонки / северные дисциплины + Лыжные гонки и северные дисциплины Трассы для северных дисциплин или лыжных гонок. Персональный транспортёр Количество изменений @@ -3334,7 +3334,7 @@ Правки OSM Поменять местами %1$s и %2$s Трек сохранён - Не указано имя файла + Пустое имя файла Очистить %1$s\? Узловые сети Предлагаемые карты @@ -3561,7 +3561,7 @@ Пересчитывать маршрут в случае отклонения %1$s из %2$s Настройка минимального и максимального уровней масштабирования, при которых слой будет отображаться. - Показать/скрыть рельеф + Показать или скрыть рельеф Переключатель, чтобы показать или скрыть слой рельефа местности на карте. Показать рельеф Скрыть рельеф @@ -3691,8 +3691,8 @@ Скрыть общественный транспорт Показать общественный транспорт Показать/скрыть общественный транспорт - Добавить/изменить место - Создать/изменить POI + Добавить или изменить избранное + Создать или изменить POI Возврат к редактированию Парковки Переключатель, чтобы показать или скрыть общественный транспорт на карте. @@ -3796,7 +3796,7 @@ Скачать карты Википедии Эндуро мотоцикл Мотороллер - Закрытая OSM-заметка + Закрытая заметка OSM Инвалидная коляска Карт Инвалидное кресло впереди @@ -3961,4 +3961,35 @@ Подписка OsmAnd Live приостановлена История маркеров Отправить GPX-файл в OpenStreetMap + Закрыть заметку OSM + Добавить фото + Зарегистрироваться на +\nOpenPlaceReviews.org + Создать новый аккаунт + У меня уже есть аккаунт + История поиска + Моторная лодка + Добавить в OpenPlaceReviews + Добавить в Mapillary + OsmAnd показывает фотографии из нескольких источников: +\nOpenPlaceReviews — фотогорафии POI; +\nMapillary — изображения улиц; +\nWeb / Wikimedia — фотографии POI, указанные в данных OpenStreetMap. + Ресурсы + Примерный размер файла + Требуется для импорта + Выберите данные для экспорта в файл. + На устройстве свободно только %1$s. Освободите место в хранилище или снимите выбор с некоторых экспортируемых элементов. + Недостаточно места + Выберите импортируемые группы. + Выберите импортируемые элементы. + Использовать dev.openstreetmap.org + Можно войти в систему с помощью безопасного метода OAuth или используя свои имя пользователя и пароль. + Возникла проблема с подпиской. Нажмите кнопку, чтобы перейти к настройкам подписки Google Play и исправить способ оплаты. + Комментировать заметку OSM + Переключиться на использование dev.openstreetmap.org вместо openstreetmap.org для тестирования отправки заметок OSM / POI / GPX. + Фотографии предоставлены проектом открытых данных OpenPlaceReviews.org. Чтобы отправить свои фотографии, необходимо зарегистрироваться на сайте. + Невозможно отправить изображение, попробуйте позже + Выбор изображения + Каяк \ No newline at end of file diff --git a/OsmAnd/res/values-sc/phrases.xml b/OsmAnd/res/values-sc/phrases.xml index 5dcc8b52d1..f58e0f4dc5 100644 --- a/OsmAnd/res/values-sc/phrases.xml +++ b/OsmAnd/res/values-sc/phrases.xml @@ -3846,4 +3846,34 @@ Cobertura Puntu GPX Torre ràdar + Nono + Eja + Nono + Eja + Nono + Eja + Ufìtziu + Consoladu generale + Residèntzia + Missione + Commissione arta + Delegatzione + Ambassada + Consoladu + Ambassada + Suta-natzionale + Ufìtziu de rapresentàntzia + Cònsole onoràriu + Ufìtziu consolare + Agentzia consolare + Ghiadu dae unu cònsole + Nuntziadura + Setzione de interessos + Filiale + Ghiada dae un\'ambassadore + Ufìtziu de collegamentu + Servìtzios pro sos tzitadinos + Vistos pro immigrantes + Vistos pro no immigrantes + Ufìtziu de collegamentu \ No newline at end of file diff --git a/OsmAnd/res/values-sc/strings.xml b/OsmAnd/res/values-sc/strings.xml index fd038a717f..dd4ed9cf6b 100644 --- a/OsmAnd/res/values-sc/strings.xml +++ b/OsmAnd/res/values-sc/strings.xml @@ -786,7 +786,7 @@ Subrapositziones fluorescentes Imprea colores fluorescentes pro visualizzare rastas e àndalas. Modìficas chene lìnia - Si sa sa modìfica chene lìnia est abilitada, sas modìficas ant a èssere sarvadas in locale, in antis, e carrigadas si benit pedidu. Si nono, ant a èssere carrigadas immediatamente. + Si sa modìfica chene lìnia est abilitada, sas modìficas ant a èssere sarvadas in locale, in antis, e carrigadas si benit pedidu. Si nono, ant a èssere carrigadas immediatamente. Sa modìficas de sos PDI intre s’aplicatzione non tenent efetos in sas mapas iscarrigadas, sunt imbetzes sarvadas in su dispositivu. {0} PDI/notas carrigados/as Càrriga sa modìfica in OSM @@ -2639,7 +2639,7 @@ Còpia sa positzione/su nùmene de su PDI Logu chene nùmene Ammustra sas notas serradas - Ammustra/cua sas notas OSM in sa mapa. + Ammustra o cua sas notas OSM in sa mapa. GPX - adatu pro s\'esportatzione a JOSM o a àteros editores OSM. OSC - adatu pro s\'esportatzione in OpenStreetmap. Documentu GPX @@ -3084,9 +3084,9 @@ Ischerta sos profilos chi cheres chi siant visìbiles in s’aplicatzione. Profilos de s\'aplicatzione Annanghe a su mancu un\'elementu a sa lista in sas impostatziones pro sas atziones lestras - Iscì alpinu/de achirrada + Iscì alpinu e de achirrada Pistas pro iscì alpinu o de achirrada e atzessu a sos impiantos de artiada. - Iscì de fundu/nòrdicu + Iscì de fundu e nòrdicu Pistas pro s\'iscì nòrdicu o de fundu. Iscì-alpinismu Àndalas pro s\'iscì-alpinismu. @@ -3577,7 +3577,7 @@ Umbraduras de sos rilievos %1$s de %2$s Pistas - Ammustra / cua su terrinu + Ammustra o cua su terrinu Cua su terrinu Ammustra su terrinu Unu butone pro ammustrare o cuare s\'istratu de su terrinu in sa mapa. @@ -3695,11 +3695,11 @@ Podes atzèdere a custas atziones incarchende su butone \"%1$s\". Cua sos trasportos pùblicos Ammustra sos trasportos pùblicos - Ammustra/cua sos trasportos pùblicos + Ammustra o cua sos trasportos pùblicos Butone pro ammustrare o cuare sos trasportos pùblicos in sa mapa. - Crea / Modìfica unu PDI + Crea o modìfica unu PDI Logos de parchègiu - Annanghe / Modìfica unu preferidu + Annanghe o modìfica unu preferidu Riprìstina s\'òrdine predefinidu de sos elementos Torra a modificare Su butone de atzione faghet colare dae unu profilu ischertadu a s\'àteru. @@ -3852,7 +3852,7 @@ Sighi cun sa registratzione de su biàgiu Sarva comente documentu de rasta %s documentos de rasta ischertados - Dislinda s’intervallu pro sa registratzione generale de sas rastas (abilitadu pro mèdiu de su widget registratzione GPX in sa mapa). + Dislinda s’intervallu pro sa registratzione generale de sas rastas (allutu pro mèdiu de su widget \'Registratzione GPX\' in sa mapa). Registra Àndala de una rasta Sighi sa rasta @@ -3887,7 +3887,7 @@ Torra a fàghere • Funtzionalidade de pranificatione de un\'àndala agiornada: permitit de impreare castas diferentes de navigatzione pro segmentu e s\'inclusione de rastas \n -\n • Menù de Aparèntzia nou pro sas rastas: ischerta su colore, grussària, visulaizatzione de sas fritzas de diretzione, iconas de incumintzu/fine +\n • Menù de Aparèntzia nou pro sas rastas: ischerta su colore, grussària, visulaizatzione de sas fritzas de diretzione, iconas de incumintzu e fine \n \n • Visibilidade megiorada de sos nodos pro sas bitzicletas. \n @@ -3903,7 +3903,7 @@ Ùrtima modìfica Nùmene: Z – A Nùmene: A – Z - Iconas de incumintzu/fine + Iconas de incumintzu e fine Gràtzias pro àere comporadu \'Curvas de livellu\' Costu periòdicu de s\'abbonamentu. Lu podes anullare in AppGallery cando boles. Su pagamentu at a èssere addebitadu a su contu tuo de AppGallery cando sa còmpora at a èssere cunfirmada. @@ -3923,7 +3923,7 @@ Intra cun OAuth pro impreare sas funtzionalidades osmedit Intra impreende OAuth Iscantzella su getone OAuth de OpenStreetMap - Essida fata chene problemas + Essidu Su documentu est giai importadu in OsmAnd Imprea un\'algoritmu de càrculu de s\'àndala A* a duas fases Pro sa ghia de motoislitas cun caminos e rastas dedicados. @@ -3947,7 +3947,7 @@ Depes annànghere a su mancu duos puntos Intra in OpenStreetMap Intra in OpenStreetMap.org - Identìfica·ti cun OpenStreetMap + Intra cun OpenStreetMap Depes intrare pro pòdere carrigare modìficas noas o mudadas. \n \nPodes intrare impreende su mètodu seguru OAuth o cun s\'identificadore (su nùmene de impreadore) tuo e sa crae de intrada tua. @@ -3962,17 +3962,38 @@ Cronologia de sos marcadores Imbia unu documentu GPX a OpenStreetMap Inserta sas etichetas iscrobadas dae vìrgulas. - Pùblica cheret nàrrere chi sa rasta at a èssere ammustrada in manera pùblica in sas rastas GPS tuas e in sas listas de rastas GPS pùblicas. Sos datos frunidos pro mèdiu de s\'API non sunt ligados a sa pàgina de sa rasta tua. Sas datas integradas in sos puntos de rasta no ant a èssere a disponimentu pro mèdiu de s\'API GPS, e sos puntos no ant a èssere ordinados in manera cronològica. Nointames custu sos àteros impreadores ant a pòdere iscarrigare sa rasta su matessi dae sa lista pùblica de sas rastas cun totu sas datas e sas oras integradas. - Privada cheret nàrrere chi sa rasta no at a èssere ammustrada in peruna lista, ma sos puntos suos ant a èssere a disponimentu su matessi pro mèdiu de s\'API GPS pùblicu chene datas e oras ma no ant a èssere ordinados in manera cronològica. - Identificàbile cheret nàrrere chi sa rasta at a èssere ammustrada in manera pùblica in sas rastas GPS tuas e in sas listas de rastas GPS pùblicas. Est a nàrrere chi àteros impreadores ant a pòdere iscarrigare sa rasta e l\'ant a pòdere assotziare a su nùmene de impreadore tuo. Sos datos frunidos pro mèdiu de s\'API de sos puntos de sas rastas ant a èssere ligados a sa pàgina de sa rasta originale tua. Sas datas e sas oras de sos puntos ant a èssere a disponimentu pro mèdiu de s\'API GPS pùblicu. - Arrastàbile cheret nàrrere chi sa rasta no at a èssere ammustrada in peruna lista pùblica ma sos puntos suos ant a èssere a disponimentu su matessi pro mèdiu de s\'API GPS pùblicu cun sas datas. Àteros impreadores ant a pòdere iscarrigare petzi puntos de rasta protzessados dae sa rasta tua chi no ant a èssere assotziados diretamente cun tie. + \"Pùblica\" cheret nàrrere chi sa rasta at a èssere ammustrada in manera pùblica in sas rastas GPS tuas, in sas listas de rastas GPS pùblicas e in sa lista de rastas pùblicas cun datas e oras in forma originale. Sos datos frunidos pro mèdiu de s\'API non sunt ligados a sa pàgina de sa rasta tua. Sas datas e sas oras integradas in sos puntos de rasta no ant a èssere a disponimentu pro mèdiu de s\'API GPS, e sos puntos no ant a èssere ordinados in manera cronològica. + \"Privada\" cheret nàrrere chi sa rasta no at a èssere ammustrada in peruna lista, ma sos puntos suos ant a èssere a disponimentu su matessi, in òrdine cronològicu, pro mèdiu de s\'API GPS pùblica chene datas e oras. + \"Identificàbile\" cheret nàrrere chi sa rasta at a èssere ammustrada in manera pùblica in sas rastas GPS tuas e in sas listas de rastas GPS pùblicas. Est a nàrrere chi àteros impreadores ant a pòdere iscarrigare sa rasta e l\'ant a pòdere assotziare a su nùmene de impreadore tuo. Sos puntos de rastas cun datas e oras dae s\'API GPS frunidos pro mèdiu de s\'API de sos puntos de sas rastas ant a èssere ligados a sa pàgina de sa rasta originale tua. + \"Arrastàbile\" cheret nàrrere chi sa rasta no at a èssere ammustrada in peruna lista pùblica, ma sos puntos suos cun sas datas (no ant a èssere assotziados diretamente cun tie) l\'ant a èssere pro mèdiu de iscarrigamentos dae s\'API GPS pùblica. Serra sa nota de OSM Cummenta sa nota de OSM Podes intrare impreende su mètodu seguru OAuth o cun su nùmene tuo e sa crae de intrada tua. Annanghe una fotografia Registra·ti in \nOpenPlaceReviews.org - Sas fotografias benint frunidas dae su progetu a datos abertos OpenPlaceReviews.org. Pro pòdere carrigare sas fotografias tuas ti depes registrare in su situ. + Sas fotografias benint frunidas dae su progetu a datos abertos OpenPlaceReviews.org. Pro carrigare sas fotografias tuas ti depes registrare a su situ. Crea unu contu nou Tèngio giai unu contu + Cronologia de chirca + Kàyak + Motoscafu + Annanghe a Mapillary + Annanghe a OpenPlaceReviews + OsmAnd ammustrat fotografias dae fontes medas: +\nOpenPlaceReviews - fotografias de sos PDI; +\nMapillary - immàgines a livellu de su caminu; +\nWeb / Wikimedia - fotografias de sos PDI dillindadas in sos datos de OpenStreetMap. + Risursas + Mannària aprossimativa de su documentu + Ischerta sos datos de esportare in su documentu. + Netzessàriu pro s\'importatzione + Su dispositivu tuo tenet petzi %1$s a disponimentu. Lìbera unu pagu de memòria o boga s\'ischerta a unos cantos elementos de esportare. + Non b\'at logu bastante + Ischerta sos grupos de importare. + Ischerta sos elementos de importare. + Cola a impreare dev.openstreetmap.org in logu de openstreetmap.org pro proare su carrigamentu de sas notas OSM / PDI / GPX. + Imprea dev.openstreetmap.org + Impossìbile carrigare s\'immàgine, torra a proare prus a tardu + Ischerta un\'immàgine \ No newline at end of file diff --git a/OsmAnd/res/values-sk/strings.xml b/OsmAnd/res/values-sk/strings.xml index 2f0404d1dc..264a62d5fb 100644 --- a/OsmAnd/res/values-sk/strings.xml +++ b/OsmAnd/res/values-sk/strings.xml @@ -1919,7 +1919,7 @@ Aplikácia teraz má povolenie zapisovať do externého úložiska, ale je potrebný reštart aplikácie. Podrobný prehľad Meno a heslo pre OSM - Názov súboru obsahuje nepovolený znak + Nepovolený znak v názve súboru Tenké Stredné Tučné @@ -2636,7 +2636,7 @@ Kopírovať názov bodu/umiestnenia Nepomenované miesto Zobraziť uzavreté poznámky - Zobraziť/skryť OSM poznámky na mape. + Zobraziť alebo skryť OSM poznámky na mape. GPX - vhodné na export do JOSM a iných editorov OSM. OSC - vhodné na export do OSM. Súbor GPX @@ -3080,7 +3080,7 @@ Zmeňte priblíženie mapy pomocou posúvania kolieskom nahor a nadol. Esc vás vráti do aplikácie WunderLINQ. Použiť WunderLINQ na približovanie Pridajte aspoň jednu položku do zoznamu v nastaveniach \'Rýchlej akcie\' - Alpské/zjazdové lyžovanie + Alpské alebo zjazdové lyžovanie Svahy pre alpské a zjazdové lyžovanie a prístup k vlekom. Bežkovanie Trasy pre beh na lyžiach. @@ -3346,7 +3346,7 @@ Zameniť %1$s a %2$s Východzí bod Stopa uložená - Názov súboru je prázdny + Prázdny názov súboru Vrátiť späť Zobraziť sieť cyklotrás Vymazať %1$s\? @@ -3574,7 +3574,7 @@ Trasa bude prepočítaná ak vzdialenosť od trasy k aktuálnej polohe je väčšia ako zvolená hodnota. %1$s z %2$s Sklony svahov - Zobraziť / skryť terén + Zobraziť alebo skryť terén Skryť terén Zobraziť terén Tlačidlo pre zobrazenie alebo skrytie vrstvy terénu na mape. @@ -3693,11 +3693,11 @@ \n Skryť verejnú dopravu Zobraziť verejnú dopravu - Zobraziť/skryť verejnú dopravu + Zobraziť alebo skryť verejnú dopravu Tlačidlo na zobrazenie alebo skrytie verejnej dopravy na mape. - Vytvoriť / Upraviť bod záujmu + Vytvoriť alebo upraviť bod záujmu Parkovacie miesta - Pridať / Upraviť obľúbený bod + Pridať alebo upraviť obľúbený bod Obnoviť predvolené poradie položiek Naspäť k úpravám K týmto akciám sa dostanete stlačením tlačidla “%1$s”. @@ -3904,7 +3904,7 @@ Naposledy zmenené Názov: Z – A Názov: A – Z - Ikony štartu/cieľa + Ikony štartu a cieľa Ďakujeme za zakúpenie modulu \'Vrstevnice\' Predplatné bude spoplatnené v zvolenom intervale. Predplatné zrušte kedykoľvek na AppGallery. Platba bude stiahnutá z vášho účtu AppGallery po potvrdení nákupu. @@ -3922,10 +3922,10 @@ Natívna hromadná doprava (vo vývoji) Prepnúť na výpočet trasy hromadnej dopravy v Jave (bezpečné) Čo je nové - Vykonať prihlásenie cez OAuth pre použitie funkcií upravovania OSM + Prihláste sa cez OAuth pre použitie funkcií upravovania OSM Prihlásiť pomocou OAuth Vymazať token OpenStreetMap OAuth - Odhlásenie úspešné + Odhlásené Pre jazdu na snežnom vozidle po na to určených cestách. Súbor je už importovaný v OsmAnd Použiť dvojfázový algoritmus A* na výpočet trasy @@ -3953,13 +3953,13 @@ Predplatné OsmAnd Live skončilo Predplatné OsmAnd Live je pozastavené Predplatné OsmAnd Live je zablokované - Prihlásiť sa do OpenStreetMap - Prihlásiť sa do OpenStreetMap.org - Zaregistrovať sa do OpenStreetMap - Musíte sa prihlásiť pre odoslanie nových alebo zmenených údajov. + Prihlásenie pre OpenStreetMap + Prihlásenie pre OpenStreetMap.org + Prihlásiť sa do OpenStreetMap + Prihláste sa pre odoslanie nových alebo zmenených údajov, \n -\nMôžete sa prihlásiť pomocou bezpečnej metódy OAuth alebo pomocou mena a hesla. - Použiť meno a heslo +\nbuď pomocou metódy OAuth alebo pomocou mena a hesla. + Prihlásiť sa menom a heslom Účet Prihlasovacie meno História značiek @@ -3967,11 +3967,30 @@ Zadajte značky oddelené čiarkou. Zatvoriť OSM poznámku Komentovať OSM poznámku - Môžete sa prihlásiť bezpečnou metódou OAuth alebo použite meno a heslo. + Prihláste sa bezpečnou metódou OAuth alebo použite meno a heslo. Pridať foto Zaregistrovať na \nOpenPlaceReviews.org - Fotografie sú poskytované projektom OpenPlaceReviews.org s otvorenými dátami. Na odoslanie vašich fotiek sa musíte zaregistrovať na webovej stránke. + Prihláste sa na webstránke projektu OpenPlaceReviews.org s otvorenými dátami pre odoslanie ďalších fotografií. Vytvoriť nový účet Už mám účet + História hľadania + Kajak + Motorový čln + Pridať do Mapillary + Pridať do OpenPlaceReviews + OsmAnd szobrazuje fotografie z rôznych zdrojov: +\nOpenPlaceReviews - fotografie bodov záujmu; +\nMapillary - fotografie z ulice; +\nWeb / Wikimedia - fotografie bodov záujmu špeficikované v údajoch OpenStreetMap. + Zdroje + Približná veľkosť súboru + Zvoľte údaje na export do súboru. + Potrebné pre import + Na vašom zariadení je len %1$s voľného miesta. Prosím uvoľnite miesto alebo zrušte niektoré položky z exportu. + Nie je dostatok miesta + Zvoľte skupiny, ktoré budú importované. + Zvoľte položky, ktoré budú importované. + Prepnúť na dev.openstreetmap.org namiesto openstreetmap.org pre otestovanie odosielania OSM poznámok / bodov záujmu / GPX stôp. + Použiť dev.openstreetmap.org \ No newline at end of file diff --git a/OsmAnd/res/values-sr/phrases.xml b/OsmAnd/res/values-sr/phrases.xml index f764fee95c..69b1046618 100644 --- a/OsmAnd/res/values-sr/phrases.xml +++ b/OsmAnd/res/values-sr/phrases.xml @@ -3815,4 +3815,51 @@ Калдера Мар Стрелица: не + Табла одласка: не + Не + Да + Не + Да + Не + Да + Поднационални + Представништво + Канцеларија + Почасни конзулат + Генерални конзулат + Конзуларна канцеларија + Конзуларна агенција + На челу са конзулом + Резиденција + Нунцијатура + Мисија + Интересни + Висока комисија + Делегација + Подружница + На челу са амбасадором + Посредник + Амбасада + Радарски торањ + Паркинг + Паркинг + Таван + ГПКС тачка + ЛНГ + Продавница ораха + Кошница + Распоред + Стварно време + Кашњење + Да + Лифт + Мали електрични уређаји + Услуге за грађане + Имигрантске визе + Неимигрантске визе + Посредник + Конзулат + Амбасада + Табла + Доливање воде за пиће \ No newline at end of file diff --git a/OsmAnd/res/values-sr/strings.xml b/OsmAnd/res/values-sr/strings.xml index e0ac87a53f..c96a4e09e4 100644 --- a/OsmAnd/res/values-sr/strings.xml +++ b/OsmAnd/res/values-sr/strings.xml @@ -3865,8 +3865,35 @@ Промените врсту руте након Шта је ново Име фајла - + Паузирај снимање пута Додајте бар две тачке. Одјава успешна + „Приватно“ значи да се траг не појављује ни на једној јавној листи, али су тачке праћења у њему у нехронолошком редоследу доступне путем јавног ГПС АПИ-ја без временских ознака. + „Могуће је идентификовати“ значи да ће се траг јавно приказати у вашим ГПС траговима и у јавним списковима ГПС трагова, тј. други корисници ће моћи да преузму необрађени траг и повежу га са вашим корисничким именом. Јавни подаци о временским тачкама трага из ГПС АПИ-ја који се сервирају путем АПИ-ја за тачке праћења имаће референцу на вашу оригиналну страницу праћења. + „Следљиво“ значи да се траг не приказује нигде на јавним листама, али обрађене тачке праћења са временским ознакама у њима (које не могу бити директно повезане са вама) иду кроз преузимања са јавног ГПС АПИ-ја. + Затвори ОСМ белешку + Коментар ОСМ напомене + Пријавите се помоћу сигурне методе ОАутх или користите своје корисничко име и лозинку. + Додај фотографију + Региструјте се на +\nOpenPlaceReviews. + Пријавите се на веб локацију пројекта отворених података OpenPlaceReviews.орг да бисте отпремили још више фотографија. + Направите нови налог + Већ имам + Претрага + Кајак + Моторни чамац + Додај у Мапилари + Додај у ОпенПлејсРевјуз + ОсмАнд приказује фотографије из неколико извора: +\nОпенПлејсРевјуз - ПОИ фотографије; +\nМапилари - слике на нивоу улице; +\nВеб / Викимедиа - ПОИ фотографије наведене у подацима ОпенСтритМап. + Ресурси + Приближна величина датотеке + Изаберите податке за извоз у датотеку. + Потребно за увоз + Уређај има слободно само %1$s. Ослободите мало простора или поништите одабир неких предмета за извоз. + Нема довољно простора \ No newline at end of file diff --git a/OsmAnd/res/values-sv/strings.xml b/OsmAnd/res/values-sv/strings.xml index a1bda1b036..c6cd3aca26 100644 --- a/OsmAnd/res/values-sv/strings.xml +++ b/OsmAnd/res/values-sv/strings.xml @@ -2842,7 +2842,7 @@ Vänligen tillhandahåll fullständig kod Mjuk Ytfasthet %s är sparat - Öppet spår + Öppna spår Spår %s är sparat Ta bort mellanrum Överväg tillfälliga begränsningar diff --git a/OsmAnd/res/values-tr/phrases.xml b/OsmAnd/res/values-tr/phrases.xml index 45103c30c5..8489842899 100644 --- a/OsmAnd/res/values-tr/phrases.xml +++ b/OsmAnd/res/values-tr/phrases.xml @@ -3130,4 +3130,6 @@ Sütun Gölet Gölet + Konsolosluk + Büyük elçilik \ No newline at end of file diff --git a/OsmAnd/res/values-tr/strings.xml b/OsmAnd/res/values-tr/strings.xml index 0f284bf937..2b389e2483 100644 --- a/OsmAnd/res/values-tr/strings.xml +++ b/OsmAnd/res/values-tr/strings.xml @@ -535,7 +535,7 @@ Floresan üst katmanlar İzlenen yolları ve rotaları görüntülemek için floresan renkler kullan. Çevrim dışı düzenleme - Her zaman çevrim dışı düzenlemeyi kullanın. + Çevrim dışı düzenleme etkinleştirilirse, değişiklikler önce yerel olarak kaydedilecek ve istek üzerine karşıya yüklenecek, aksi takdirde değişiklikler hemen karşıya yüklenecek. Uygulama içinde POI değişiklikleri indirilen harita dosyalarını etkilemez, bunun yerine değişiklikler cihazınızda bir dosya olarak kaydedilir. Yükleniyor… {0} POI/not karşıya yüklendi @@ -1236,7 +1236,7 @@ Vazgeç seçili Seçimini kaldırın - Tüm Seçimleri Kaldır + Tüm seçimleri kaldır Daralt İzlenen yollar Şu anda kaydedilen yol @@ -1854,7 +1854,7 @@ Şunun için rapor Veri mevcut değil Durum - Değişiklikleri Kaydet + Değişiklikleri kaydet E-posta adresi Yeraltı nesneleri Devamını oku @@ -1943,7 +1943,7 @@ Uygulamanın şimdi harici depolamaya yazma izni var, ancak bunu yapmak için yeniden başlatılması gerekir. Tam rapor OSM kullanıcı adı ve parolası - Dosya adı geçersiz karakter içermektedir + Dosya adında geçersiz karakter 7/24 açık Bellek kartı Koordinat biçimi @@ -2805,7 +2805,7 @@ POI etiketleri Yarın şu saatte açılıyor Kapalı notları göster - Haritada OSM notlarını göster/gizle. + Haritada OSM notlarını göster veya gizle. GPX - JOSM veya diğer OSM düzenleyicilerine aktarmak için uygundur. OSC - OSM\'ye aktarmak için uygundur. OSC dosyası @@ -3156,7 +3156,7 @@ Sık Kullanılanları içe aktarın veya haritadaki noktaları işaretleyerek ekleyin. GPX dosyasını içe aktar %1$s dosyası ara noktalar içermiyor, izlenen yol olarak içe aktar\? - Hareket Noktası + Noktayı Taşı OSM alıcıları Toplam bağış kapalı @@ -3186,9 +3186,9 @@ Gündüz/gece modunu değiştir Parke veya kaldırım taşı yok \'Hızlı eylem\' ayarlarında listeye en az bir öge ekleyin - Alp/yokuş aşağı kayak + Alp ve yokuş aşağı kayak Alp veya yokuş aşağı kayak ve kayak teleferiklerine erişim için yamaçlar. - Kros/İskandinav kayak + Kros ve İskandinav kayak İskandinav veya kros kayağı pistleri. Kayak turu Kayak turu rotaları. @@ -3322,7 +3322,7 @@ Başlangıç noktası Bilinmeyen yol türleri için varış zamanını tahmin eder ve tüm yollar için hızı sınırlar (güzergahı etkileyebilir) Yol izi kaydedildi - Dosya adı boş + Boş dosya adı Eski haline döndür Ekranın, kalkış noktasını ortalamasını sağlamak için bir düğme. Daha sonra hedef belirlemeyi veya rota hesaplamasını tetiklemeyi isteyecektir. Düğüm ağı bisiklet rotalarını göster @@ -3384,7 +3384,7 @@ Kullanıcı adı ve parola Bu eklenti ayarları geneldir ve tüm profiller için geçerlidir OSM düzenleme - Yüklenmemiş tüm düzenlemelerinizi veya OSM hatalarınızı %1$s\'de görüntüleyebilirsiniz. Karşıya yüklenen noktalar OsmAnd\'da gösterilmez. + Henüz karşıya yüklenmemiş tüm düzenlemelerinizi veya OSM hatalarınızı %1$s\'de görüntüleyebilirsiniz. Karşıya yüklenen noktalar OsmAnd\'da gösterilmez. OSM Navigasyon sırasında veya harekete halindeyken gösterilen simge. Dinlenme anında gösterilen simge. @@ -3495,7 +3495,7 @@ Hepsini değiştir Her ikisini de sakla İçe aktarılan ögelere ön ek eklenecek - OsmAnd\'da içe aktarılanlarla aynı isme sahip ögeler zaten var. + OsmAnd\'da içe aktarılanlarla aynı ada sahip ögeler zaten var. \n \nBir eylem seçin. Bazı ögeler zaten var @@ -3532,7 +3532,7 @@ Güzergahtan geçerli konuma olan mesafe seçilen değerden fazla ise güzergah yeniden hesaplanacaktır. %1$s / %2$s Yamaçlar - Araziyi göster / gizle + Araziyi göster veya gizle Araziyi gizle Araziyi göster Haritada arazi katmanını göstermek veya gizlemek için bir düğme. @@ -3650,11 +3650,11 @@ Bu eylemlere “%1$s” düğmesine dokunarak erişebilirsiniz. Toplu taşıma araçlarını gizle Toplu taşıma araçlarını göster - Toplu taşıma araçlarını göster/gizle + Toplu taşıma araçlarını göster veya gizle Haritada toplu taşıma araçlarını gösteren veya gizleyen düğme. - POI Oluştur / Düzenle + POI oluştur veya düzenle Park etme alanları - Sık Kullanılan Ekle / Düzenle + Sık kullanılan ekle veya düzenle Öntanımlı öge sıralamasını geri yükle Düzenlemeye geri dön Eylem düğmesi seçilen profiller arasında geçiş yapar. @@ -3779,7 +3779,7 @@ Bitti Yolun üzerine yaz Ardından, bu seçeneği kullanmak için navigasyon profillerinizden biriyle izlenen yolunuzu izin verilen en yakın yola tutturun. - Yeni bir yol olarak kaydet + Yeni bir izleme olarak kaydet 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. @@ -3811,7 +3811,7 @@ Yol dosyası olarak kaydet %s yol dosyası seçildi (Son uygulamalar aracılığıyla) uygulama kapatıldığında yol kaydını duraklatacaktır. (OsmAnd arka plan göstergesi Android bildirim çubuğundan kaybolur.) - Genel yol kaydı için kayıt aralığını seçin (haritadaki seyahat kayıt widget\'ı aracılığıyla etkin). + Genel yol kaydı için kayıt aralığını belirtin (haritadaki \'Seyahat kaydetme\' widget\'ı aracılığıyla açıldı). Seyahat kaydetmeyi duraklat Seyahat kaydetmeyi devam ettir En yakın nokta @@ -3843,7 +3843,7 @@ Basitleştirilmiş yol • Güzergah planlama işlevi güncellendi: her bölüm için farklı navigasyon türlerinin kullanılmasına ve izlenen yolların dahil edilmesine izin veriliyor \n -\n • İzlenen yollar için yeni görünüm menüsü: renk ve kalınlık seçimi, yön oklarının gösterilmesi, başlangıç/bitiş simgeleri +\n • İzlenen yollar için yeni görünüm menüsü: renk ve kalınlık seçimi, yön oklarının gösterilmesi, başlangıç ve bitiş simgeleri \n \n • Bisiklet düğümlerinin görünürlüğü iyileştirildi. \n @@ -3859,7 +3859,7 @@ Son değiştirme İsim: Z – A İsim: A – Z - Başlangıç/bitiş simgeleri + Başlangıç ve bitiş simgeleri \'Eş yükselti eğrileri\'ni satın aldığınız için teşekkürler Abonelik seçilen dönem başına ücretlendirilir. İstediğiniz zaman AppGallery\'den iptal edin. Ödeme, satın alma onaylandığında AppGallery hesabınızdan alınacaktır. @@ -3877,10 +3877,10 @@ Yerel Toplu Taşıma geliştirme Java (güvenli) Toplu Taşıma yönlendirme hesaplamasına geçin Yenilikler - osmedit özelliklerini kullanmak için OAuth oturum açma işlemi gerçekleştirin + osmedit özelliklerini kullanmak için OAuth ile oturum açın OAuth ile oturum aç OpenStreetMap OAuth belirtecini temizle - Oturum kapatma başarılı + Oturum kapatıldı Dosya zaten OsmAnd\'da içe aktarıldı 2 aşamalı A* yönlendirme algoritması kullan Ayrılmış yollar ve parkurlarla kar arabası sürüşü için. @@ -3903,12 +3903,12 @@ Acil Seyahat En az iki nokta eklemelisiniz - OpenStreetMap\'te oturum aç - OpenStreetMap.org\'da oturum aç - Yenilikleri veya değişiklikleri karşıya yüklemek için oturum açmanız gerekir. + OpenStreetMap için oturum aç + OpenStreetMap.org için oturum aç + Yenilikleri veya değişiklikleri karşıya yüklemek için oturum açın, \n -\nGüvenli OAuth yöntemini kullanarak oturum açabilir veya kullanıcı adı ve parolanızı kullanabilirsiniz. - Kullanıcı adı ve parola kullan +\nOAuth ile oturum açabilir veya kullanıcı adı ve parolanızı kullanabilirsiniz. + Kullanıcı adı ve parola ile oturum aç Kullanıcı adı Hesap Aboneliği yönet @@ -3920,4 +3920,36 @@ İşaretleyiciler geçmişi GPX dosyasını OpenStreetMap\'e gönder Virgülle ayrılmış etiketleri girin. + \"Genel\", izlemenin GPS izlerinizde ve genel GPS izleme listelerinde herkese açık olarak ve ham biçimde zaman damgalarıyla birlikte genel izleme listesinde gösterileceği anlamına gelir. API aracılığıyla sunulan veriler, izleme sayfanızı göstermez. İzleme noktası zaman damgaları, genel GPS API\'si aracılığıyla kullanılamaz ve izleme noktaları kronolojik olarak sıralanmaz. + \"Özel\", izlemenin herkese açık herhangi bir listede gösterilmediği, ancak ondan alınan izleme noktalarının zaman damgası olmadan genel GPS API\'si aracılığıyla eşzamanlı olmayan sırada kullanılabileceği anlamına gelir. + \"Teşhis edilebilir\", izlemenin GPS izlerinizde ve genel GPS izleme listelerinde herkese açık olarak gösterileceği anlamına gelir, yani diğer kullanıcılar ham izi indirebilir ve kullanıcı adınızla ilişkilendirebilir. İzleme noktaları API\'si aracılığıyla sunulan GPS API\'sinden alınan herkese açık zaman damgalı izleme noktası verileri, orijinal izleme sayfanızı gösterecektir. + \"Takip edilebilir\", izlemenin herkese açık herhangi bir listede gösterilmediği, ancak (sizinle doğrudan ilişkilendirilemeyen) zaman damgaları olan işlenen izleme noktalarının herkese açık GPS API\'sinden indirmeler yoluyla göründüğü anlamına gelir. + OSM Notunu Kapat + OSM Notuna Yorum Yap + Güvenli OAuth yöntemini kullanarak oturum açın veya kullanıcı adınızı ve parolanızı kullanın. + Fotoğraf ekle + OpenPlaceReviews.org\'a +\nkaydolun + Daha da fazla fotoğraf yüklemek için açık veri projesi web sitesi OpenPlaceReviews.org\'da oturum açın. + Yeni hesap oluştur + Zaten bir hesabım var + Arama geçmişi + Kano + Motorlu tekne + Mapillary\'ye ekle + OpenPlaceReviews\'a ekle + OsmAnd çeşitli kaynaklardan fotoğraflar gösterir: +\nOpenPlaceReviews - POI fotoğrafları; +\nMapillary - sokak seviyesi görüntüleri; +\nİnternet / Wikimedia - OpenStreetMap verilerinde belirtilen POI fotoğrafları. + Kaynaklar + Yaklaşık dosya boyutu + Dosyaya aktarılacak verileri seçin. + İçe aktarma için gerekli + Aygıtınızda yalnızca %1$s boş alan var. Lütfen biraz alan boşaltın veya dışa aktarılacak bazı ögelerin seçimini kaldırın. + Yeterli alan yok + İçe aktarılacak grupları seçin. + İçe aktarılacak ögeleri seçin. + OSM Notu/POI/GPX yüklemeyi test etmek için openstreetmap.org yerine dev.openstreetmap.org kullanmaya geçin. + dev.openstreetmap.org\'u kullan \ No newline at end of file diff --git a/OsmAnd/res/values-uk/phrases.xml b/OsmAnd/res/values-uk/phrases.xml index cc955e79c5..70d6d83d6b 100644 --- a/OsmAnd/res/values-uk/phrases.xml +++ b/OsmAnd/res/values-uk/phrases.xml @@ -3838,4 +3838,34 @@ Дах Точка GPX Радіолокаційна вежа + Багатонаціональне + Нунціатура + Розділ інтересів + Зв\'язок + Послуги для громадян + Імміграційні візи + Неімміграційні візи + Зв\'язок + Ні + Так + Ні + Так + Ні + Так + Представництво + Офіс + Почесний консул + Генеральне консульство + Консульський офіс + Консульський орган + Очолює консул + Резиденція + Місія + Верховний комісаріат + Делегація + Відділення + Очолює посол + Посольство + Консульство + Посольство \ No newline at end of file diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml index 4abd682cde..a9a6d024db 100644 --- a/OsmAnd/res/values-uk/strings.xml +++ b/OsmAnd/res/values-uk/strings.xml @@ -59,7 +59,7 @@ Видимість Теги Опис - Для вивантаження GPX-файлів, будь ласка, вкажіть Ваше ім\'я користувача і пароль в OSM. + Для вивантаження GPX-файлів вкажіть ваше ім\'я користувача і пароль в OSM. Підтримка Підтримати розробку нових функцій Відображати масштаб @@ -1946,7 +1946,7 @@ Це потрібно, щоб надавати Вам відомості про зміни на мапі. Прилюдне імʼя Територія - Будь ласка, введіть прилюдне ім\'я + Введіть загальнодоступне ім\'я Дякуємо за підтримку OsmAnd! \nЩоб задіяти усі нові можливості Вам потрібно перезапустити застосунок. Частина коштів буде спрямована землеписцям OSM, що внесли зміни до мапи в цьому місці. @@ -1956,7 +1956,7 @@ \nЯкщо Вам подобається OsmAnd та OSM, і хочете підтримати і бути підтриманими ними, це ідеальний спосіб зробити це. Надішліть Вашу OSM-нотатку таємно, або скориставшись обліковим записом на OSM.org. Надіслати нотатку в OSM - Ім\'я файлу містить неприпустимі знаки + Неприпустимі знаки в назві файлу Слідкуйте за нами Звукові напрямки Індикація звуком напряму на цільову точку. @@ -2199,7 +2199,7 @@ Повороти (точки для проходження) на цьому маршруті Точки маршруту, цікаві місця та названі можливості Трек - Максимальна швидкість + Найбільша швидкість Середня швидкість Час в русі Загальний час @@ -2243,7 +2243,7 @@ Рівень масштабування: %1$s Назва групи Зміна кольору - Редагувати ім\'я + Змінити ім\'я Огляд Виберіть вулицю у %1$s @@ -2433,7 +2433,7 @@ Перезавантажити Перезавантажити тайли, щоб переглянути актуальні дані. Тайловий кеш - Невірне ім\'я користувача + Неправильне ім\'я користувача до від Показувати лише додані зображення @@ -2464,7 +2464,7 @@ Перегляньте мапу і додайте точки Вимірювання відстані Необхідно додати хоча б одну точку. - Ім’я GPX файлу: + Назва GPX файлу: Показати на мапі після збереження Додати шляхову точку Зберегти GPX-точку шляху @@ -2633,7 +2633,7 @@ Додає першу зупинку Пересунути призначення далі і створити його Показати закриті нотатки - Показати/приховати OSM-нотатки на мапі. + Показати чи приховати примітки OSM на мапі. GPX — підходить для експорту в JOSM та інші OSM-редактори. OSC — підходить для експорту в OSM. GPX-файл @@ -2663,7 +2663,7 @@ Зх Пд Пн - Необов\'язкове ім\'я точки + Необов\'язкова назва точки Близькі маршрути в межах В межах Відстань: спочатку найдальше @@ -3068,7 +3068,7 @@ Дані зібрано Натисніть ще раз для зміни орієнтації мапи Мінімальна швидкість - Максимальна швидкість + Макс. швидкість Усталена швидкість Змінити налаштування усталеної швидкості Встановити мінімальну/максимальну швидкість @@ -3122,7 +3122,7 @@ Змінюйте масштабування мапи прокручуванням колеса вгору і вниз. Клавіша Escape поверне вас до додатку WunderLINQ. Використовувати WunderLINQ для контролю Потрібно додати принаймні одну річ до списку у налаштуваннях \'Швидкої дії\' - Високогір\'я / гірські лижі + Альпійські та гірські лижі Траси для високогірних і гірських лиж та доступ до лижних підіймачів. Бездоріжжя Налаштувати профіль @@ -3132,7 +3132,7 @@ Оберіть налаштування навігації для профілю Вкажіть верхню межу змін Кількість змін - Бігові лижі / скандинавська ходьба + Бігові лижі та скандинавські лижі Траси для скандинавської ходьби або бігу на лижах. Лижні тури Маршрути для лижних турів. @@ -3364,7 +3364,7 @@ Змінити місцями %1$s та %2$s Початкова точка Трек збережено - Ім\'я файлу порожнє + Порожня назва файлу Повернутися Показати мережеві маршрути циклу вузлів Очистити %1$s\? @@ -3574,7 +3574,7 @@ Пагорб %1$s з %2$s Схили - Показати / приховати місцевість + Показати чи приховати рельєф Сховати місцевість Показати місцевість Кнопка для відображення або приховування шару місцевості на мапі. @@ -3691,10 +3691,10 @@ Розташування припаркованого авто Приховати громадський транспорт Показати громадський транспорт - Показати/приховати громадський транспорт + Показати чи приховати громадський транспорт Кнопка показу або приховування громадського транспорту на мапі. - Створити / змінити POI - Додати / правити вибране + Створити чи змінити POI + Додати чи змінити вибране Відновити усталене впорядкування Повернутися до редагування Ви можете отримати доступ до цих дій, торкнувшись кнопки “%1$s”. @@ -3863,7 +3863,7 @@ Обрізати після Змінити вид маршруту раніше Змінити вид маршруту після - Вкажіть інтервал для загального запису поїздки (включається через віджет запису подорожі на мапі). + Вкажіть інтервал для загального запису поїздки (увімкнено через віджет «Запис подорожі» на мапі). Усталена системна Всі наступні сегменти Попередній сегмент @@ -3884,7 +3884,7 @@ Повторити • Оновлено функції планування маршруту: дозволено застосувати різні типи переходів для кожного сегмента і прив\'язати будь-який трек до доріг \n -\n• Нове меню вигляду треків: вибір кольору, товщина, вигляд стрілки напрямку, значки початку/завершення +\n• Нове меню вигляду треків: вибір кольору, товщина, вигляд стрілки напрямку, піктограми початку та завершення \n \n• Покращено оглядовість велосипедних вузлів \n @@ -3900,7 +3900,7 @@ Востаннє змінено За назвою: Я — А За назвою: А — Я - Значки початку/завершення + Піктограми початку та завершення Дякуємо за придбання «Горизонталей» Що нового Передплата стягується за вибраний період. Скасуйте її в AppGallery у будь-який час. @@ -3914,10 +3914,10 @@ Двофазна маршрутизація для автомобільної навігації. Розвиток власного громадського транспорту Перемкнутися на розрахунок маршруту громадським транспортом за допомогою Java (безпечний) - Виконати вхід OAuth для користування функцією osmedit + Увійти за допомогою OAuth для користування функцією osmedit Увійти через OAuth Очистити токен OAuth OpenStreetMap - Ви успішно вийшли + Ви вийшли OsmAnd дані в реальному часі Уникати пішохідних шляхів Уникати пішохідних шляхів @@ -3951,27 +3951,48 @@ Передплата OsmAnd Live на утриманні Увійти до OpenStreetMap.org Увійти до OpenStreetMap.org - Увійдіть, щоб вивантажити нові або внесені зміни. + Потрібно увійти, щоб вивантажити нові або внесені зміни. \n -\nВи можете увійти, за допомогою безпечного методу OAuth, або скористатися своїм ім\'ям та паролем. - Використовувати ім\'я і пароль +\nВи можете увійти за допомогою безпечного методу OAuth, або скористатися своїм іменем користувача та паролем. + Використовувати ім\'я користувача та пароль Обліковий запис Ім\'я користувача Увійти за допомогою OpenStreetMap Історія маркерів Надіслати файл GPX на OpenStreetMap Введіть мітки через коми. - Загальнодоступне означає, що трасування буде показано загальнодоступно у ваших GPS-трасуваннях та у загальнодоступних списках GPS-трасування. Дані, що подаються через API, не посилаються на вашу сторінку трасування. Мітки часу точок трасування недоступні через загальнодоступний API GPS і не впорядковані хронологічно. Однак інші користувачі все ще можуть завантажувати необроблену трасування із загальнодоступного списку трасування та будь-які часові позначки, що містяться всередині. - Приватне означає, що трасування не з\'являтиметься в жодному загальнодоступному списку, але контрольні точки з нього все одно будуть доступні через загальнодоступний API GPS без позначок часу та не впорядковані за хронологією. - Ідентифікований означає, що трасування буде показано публічно у вашому трасуванні GPS і в загальнодоступних списках трасування GPS, тобто інші користувачі зможуть завантажити необроблене трасування та пов\'язати його з вашим ім\'ям користувача. Дані, подані за допомогою API точок відстеження, посилаються на вихідну сторінку трасування. Позначки часу точок трасування доступні через загальнодоступний GPS API. - Відстежуваний означає, що трасування не з\'явиться в жодному загальнодоступному списку, але точки від нього все одно будуть доступні через загальнодоступний API GPS із позначками часу. Інші користувачі зможуть завантажувати лише оброблені контрольні точки з вашого трасування, які не можуть бути безпосередньо пов’язані з вами. + «Загальнодоступне» означає, що трасування показано загальнодоступно у ваших GPS-трасуваннях та у загальнодоступних списках GPS-трасування, а також у загальнодоступному списку трасування з позначками часу в необробленому вигляді.. Дані, що подаються через API, не посилаються на вашу сторінку трасування. Мітки часу точок трасування недоступні через загальнодоступний API GPS і не впорядковані хронологічно. + «Приватне» означає, що трасування не з\'являється в жодному загальнодоступному списку, але контрольні точки з нього в нехронологічному порядку доступні через загальнодоступний API GPS без позначок часу. + «Ідентифікований» означає, що трасування буде показано публічно у вашому трасуванні GPS і в загальнодоступних списках трасування GPS, тобто інші користувачі зможуть завантажити необроблене трасування та пов\'язати його з вашим ім\'ям користувача. Загальнодоступні дані трасування з GPS API, що обслуговуються за допомогою API точок відстеження, посилаються на початкову сторінку трасування. + «Відстежуваний» означає, що трек не з\'явиться в жодному загальнодоступному списку, але обробка точок з позначками часу від нього (які не можуть бути безпосередньо пов’язані з вами) виконується за допомогою завантажень із загальнодоступного API GPS. Закрити примітку OSM Коментувати примітку OSM - Ви можете увійти за допомогою безпечного методу OAuth або застосувавши свої ім\'я користувача й пароль. + Ви можете увійти за допомогою безпечного методу OAuth або за допомогою своїх ім\'я користувача й паролю. Додати світлини Зареєструватися на \nOpenPlaceReviews.org Світлини надаються проєктом відкритих даних OpenPlaceReviews.org. Щоб завантажити світлини зареєструйтеся на сайті. Створити обліковий запис У мене вже є обліковий запис + Журнал пошуку + Каяк + Моторний човен + Ресурси + Приблизний розмір файлу + Виберіть дані, які потрібно експортувати до файлу. + Необхідно для імпорту + На вашому пристрої лише %1$s вільного простору. Звільніть місце або приберіть позначки з деяких елементів для експорту. + Бракує простору + Додати до Mapillary + Додати до OpenPlaceReviews + OsmAnd демонструє світлини з кількох джерел: +\nOpenPlaceReviews — світлини POI; +\nMapillary - зображення вулиць; +\nМережа / Вікімедіа — світлини POI, вказані в даних OpenStreetMap. + Виберіть групи, які буде імпортовано. + Виберіть елементи, які буде імпортовано. + Перейдіть на dev.openstreetmap.org замість openstreetmap.org для випробувань завантаження Приміток / POI / GPX OSM. + Використовувати dev.openstreetmap.org + Не вдається завантажити зображення, повторіть спробу пізніше + Вибрати зображення \ No newline at end of file diff --git a/OsmAnd/res/values-zh-rTW/phrases.xml b/OsmAnd/res/values-zh-rTW/phrases.xml index cd4ea85dee..083311b0c0 100644 --- a/OsmAnd/res/values-zh-rTW/phrases.xml +++ b/OsmAnd/res/values-zh-rTW/phrases.xml @@ -1579,7 +1579,7 @@ 玩具 冰淇淋 SIM 卡 - 分公司 + 分公司/分店 戰爭紀念碑 牌匾 雕像 @@ -3849,4 +3849,34 @@ 屋頂 GPX 點 雷達塔 + + + + + + + 準外交 + 代表處 + 辦公室 + 名譽領事 + 總領事館 + 領事館 + 領事機構 + 由領事率領 + 住宅 + 代表駐地 + 代表機構 + 利益代表處 + 高級專員 + 代表團 + 分處 + 由大使率領 + 聯絡處 + 大使館 + 公民服務 + 移民簽證 + 非移民簽證 + 聯絡處 + 領事館 + 大使館 \ No newline at end of file diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml index 0a000f7811..1b6bd9fee5 100644 --- a/OsmAnd/res/values-zh-rTW/strings.xml +++ b/OsmAnd/res/values-zh-rTW/strings.xml @@ -1913,7 +1913,7 @@ 完整報告 OSM 的使用者名稱與密碼 報告 - 檔案名稱包含非法字元 + 檔案名稱中有非法字元 現在應用程式允許寫入外部記憶體。但是需要重新啟動程式。 請透過地圖增加地圖標記 未發現任何航點 @@ -2632,7 +2632,7 @@ 複製地點/POI 名稱 無名稱的位置 顯示已關閉的註解 - 在地圖上顯示/隱藏 OSM 的註解。 + 在地圖上顯示或隱藏 OSM 的註解。 GPX - 適合匯出到 JOSM 或其他 OSM 編輯。 OSC - 適合匯出到 OSM。 GPX 檔案 @@ -3078,7 +3078,7 @@ 透過向上或向下捲以變更地圖縮放。Esc 會將您帶回 WunderLINQ 應用程式。 使用 WunderLINQ 來控制 至少在「快速動作」設定中新增一個項目 - 高山/下坡滑雪 + 高山與下坡滑雪 適合高山或下山滑雪的斜坡與滑雪纜車。 越野滑雪 越野滑雪的路線。 @@ -3360,7 +3360,7 @@ 起點 估計未知道路類型的到達時間,並限制所有道路的速度(可能會影響路徑) 已儲存軌跡 - 檔案名稱為空 + 空的檔案名稱 還原 讓出發點置於畫面中央的按鈕。 顯示節點網路自行車路徑 @@ -3571,7 +3571,7 @@ 啟用以檢視地形陰影或坡度圖。您可以在我們的網站上閱讀更多關於這些地圖類型的資訊。 地形陰影 坡度 - 顯示/隱藏地形 + 顯示或隱藏地形 隱藏地形 顯示地形 用於顯示或隱藏地圖上地形圖層的按鈕。 @@ -3689,10 +3689,10 @@ 您可以透過點選「%1$s」按鈕存取這些動作。 隱藏大眾運輸 在地圖上顯示或隱藏大眾運輸的按鈕。 - 顯示/隱藏大眾運輸 - 建立/編輯 POI + 顯示或隱藏大眾運輸 + 建立或編輯 POI 停車位置 - 新增/編輯收藏 + 新增與編輯收藏 恢復預設項目排序 返回編輯 恢復 @@ -3867,7 +3867,7 @@ 檔案名稱 已選定 %s 軌跡檔案 將會在應用程式被砍除時(透過最近的應用程式)暫停軌跡錄製。(OsmAnd 背景指示會從 Android 通知列中消失。) - 指定一般軌跡錄製的記錄間隔(透過地圖上的旅程錄製小工具啟用)。 + 指定一般軌跡錄製的記錄間隔(透過地圖上的旅程錄製小工具開啟)。 暫停旅程錄製 恢復旅程錄製 系統預設 @@ -3883,7 +3883,7 @@ 重做 • 更新「規劃路線」功能:允許每個路段使用不同的導航類型並包含軌跡 \n -\n • 新的軌跡外觀選項:選取顏色、厚度、開啟方向箭頭與開始/結束圖示 +\n • 新的軌跡外觀選項:選取顏色、厚度、開啟方向箭頭與開始與結束圖示 \n \n • 改善自行車節點的能見度 \n @@ -3899,7 +3899,7 @@ 最後修改時間 名稱:Z – A 名稱:A – Z - 開始/結束圖示 + 開始與結束圖示 感謝您購買 \'Contour lines\' 按選定週期收取訂閱費用。隨時在 AppGallery 上取消。 確認購買後將會從您的 AppGallery 帳號中付款。 @@ -3917,10 +3917,10 @@ 原生公共運輸發展 切換到 Java(安全)公共運輸路線計算 有什麼新鮮事 - 執行 OAuth 登入以使用 osmedit 功能 + 以 OAuth 登入以使用 osmedit 功能 透過 OAuth 登入 清除 OpenStreetMap OAuth 權杖 - 成功登出 + 已登出 適用於有專用道路與軌道的雪地摩托車駕駛。 檔案已在 OsmAnd 匯入 使用 2 相的 A* 路線演算法 @@ -3948,29 +3948,50 @@ OsmAnd Live 訂閱已過期 OsmAnd Live 訂閱已暫停 OsmAnd Live 訂閱已暫停 - 登入到 OpenStreetMap - 登入到 OpenStreetMap.org - 您必須登入以上傳新的或修正過的變更。 + 登入 OpenStreetMap + 登入 OpenStreetMap.org + 您必須登入以上傳新的或修正的變更。 \n -\n您可以使用安全的 OAuth 方法或使用您的登入與密碼來登入。 - 使用登入與密碼 +\n您可以使用安全的 OAuth 方法或您的帳號密碼登入。 + 使用帳號與密碼 帳號 - 登入 + 帳號 使用 OpenStreetMap 登入 標記歷史 傳送 GPX 檔案到 OpenStreetMap 輸入以逗號分隔的標籤。 - 公開代表軌跡將會公開顯示在您的 GPS 軌跡與公開的 GPS 軌跡清單中。透過 API 取得的 API 不會參考您的軌跡頁面。軌跡點的時間戳不會透過公開的 GPS API 提供,也不會按時間排序。不過,其他使用者仍可以從公開的軌跡清單下載原始軌跡與任何其中包含的時間戳。 - 私有代表了軌跡不會顯示在任何公開的清單中,但其軌跡點仍可透過公開的 GPS API 取得,但沒有時間戳,也不會按時間順序排列。 - 可識別代表軌跡將會在您的 GPS 軌跡與公開 GPS 軌跡清單中顯示,亦即其他使用者將可以下載原始軌跡並將其與您的使用者名稱相關聯。透過軌跡點 API 提供的資料將會參考您的原始軌跡頁面。軌跡點的時間戳可透過公開的 GPS API 取得。 - 可追蹤代表軌跡不會顯示在任何公開的清單中,但其追蹤點仍可以透過帶有時間戳的公開 GPS API 使用。其他使用者將只能從您的軌跡中下載處理過的追蹤點,但這些追蹤點無法直接與與您相關聯。 + 「公開」代表軌跡將會公開顯示在您的 GPS 軌跡與公開的 GPS 軌跡清單中,且在公開軌跡清單中會以帶有原始形式的時間戳顯示。透過 API 取得的資料不會引用您的軌跡頁面。軌跡點的時間戳不會透過公開的 GPS API 提供,也不會按時間排序。 + 「私有」代表軌跡不會顯示在任何公開的清單中,但其軌跡點仍可透過公開的 GPS API 取得,但沒有時間戳,也不會按時間順序排列。 + 「可識別」代表軌跡將會在您的 GPS 軌跡與公開 GPS 軌跡清單中顯示,亦即其他使用者將可以下載原始軌跡並將其與您的使用者名稱相關聯。透過追蹤點 API 提供的 GPS API 中帶有公開時間戳的追蹤點資料將會引用您的原始追蹤頁面。 + 「可追蹤」代表軌跡不會在任何公開的清單中顯示,但帶有時間戳(這並不會與您直接相關聯)的已處理追蹤點可從公開的 GPS API 下載。 關閉 OSM 註記 評論 OSM 註記 您可以使用安全的 OAuth 方式或是使用您的帳號與密碼來登入。 新增照片 註冊於 \nOpenPlaceReviews.org - 照片由開放資料專案 OpenPlaceReviews.org 提供。為了上傳您的照片,您必須在網站上註冊。 + 照片由開放資料專案 OpenPlaceReviews.org 提供。為了上傳您的照片,您需要在網站上註冊。 建立新帳號 我已經有帳號了 + 搜尋歷史紀錄 + 皮艇 + 快艇 + 新增到 Mapillary + 新增到 OpenPlaceReviews + OsmAnd 從多個來源顯示照片: +\nOpenPlaceReviews - POI 照片; +\nMapillary - 街景; +\n網路/維基媒體 - 特定 OpenStreetMap 資料的 POI 照片。 + 資源 + 大約檔案大小 + 選取要匯出到檔案的資料。 + 匯入需要 + 您的裝置僅剩 %1$s 可用空間。請釋出一些空間或取消選取要匯出的部份檔案。 + 空間不足 + 選取將要被匯入的群組。 + 選取將要被匯入的項目。 + 切換到 dev.openstreetmap.org 而非 openstreetmap.org 來測試 OSM 註記/POI/GPX。 + 使用 dev.openstreetmap.org + 無法上傳圖片,請稍後再試 + 選取圖片 \ No newline at end of file diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index 0cb79d23d1..f91581adf6 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -249,6 +249,7 @@ 16dp 12dp 8dp + 6dp 8dp 13dp 5dp @@ -289,6 +290,7 @@ 1.5 128dp 8dp + 28dp 236dp 68dp @@ -395,6 +397,7 @@ 42dp 128dp 164dp + 68dp 6dp 12dp diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 7a5a9b759e..9da2ac6d86 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,12 +11,22 @@ Thx - Hardy --> + %1$s * %2$s + OsmAnd shows photos from several sources:\nOpenPlaceReviews - POI photos;\nMapillary - street-level imagery;\nWeb / Wikimedia - POI photos specified in OpenStreetMap data. + Use dev.openstreetmap.org + Switch to use "dev.openstreetmap.org" instead of "openstreetmap.org" to testing uploading OSM Note / POI / GPX. + Add to OpenPlaceReviews + Add to Mapillary + Select items that will be imported. + Select groups that will be imported. There is not enough space Your device only has %1$s free. Please free up some space or unselect some items to export. Needed for import Select the data to be exported to the file. Approximate file size Resources + Select picture + Cannot upload image, please, try again later Motorboat Kayak Search history @@ -67,10 +77,10 @@ Graph Use 2-phase A* routing algorithm File is already imported in OsmAnd - Logout successful + Logged out Clear OpenStreetMap OAuth token Log in via OAuth - Perform an OAuth Login to use osmedit features + Log in with OAuth to use osmedit features Switch to Java (safe) Public Transport routing calculation Native Public Transport development Recalculates only the initial part of the route. Can be used for long trips. diff --git a/OsmAnd/res/xml/osm_editing.xml b/OsmAnd/res/xml/osm_editing.xml index 469e841c36..8fd0883fc8 100644 --- a/OsmAnd/res/xml/osm_editing.xml +++ b/OsmAnd/res/xml/osm_editing.xml @@ -32,6 +32,14 @@ android:title="@string/offline_edition" tools:icon="@drawable/ic_action_offline" /> + + diff --git a/OsmAnd/src/net/osmand/AndroidNetworkUtils.java b/OsmAnd/src/net/osmand/AndroidNetworkUtils.java index d1ca9aa7ab..f8710927ef 100644 --- a/OsmAnd/src/net/osmand/AndroidNetworkUtils.java +++ b/OsmAnd/src/net/osmand/AndroidNetworkUtils.java @@ -305,8 +305,8 @@ public class AndroidNetworkUtils { try { boolean firstPrm = !urlText.contains("?"); StringBuilder sb = new StringBuilder(urlText); - for (String key : additionalParams.keySet()) { - sb.append(firstPrm ? "?" : "&").append(key).append("=").append(URLEncoder.encode(additionalParams.get(key), "UTF-8")); + for (Map.Entry entry : additionalParams.entrySet()) { + sb.append(firstPrm ? "?" : "&").append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8")); firstPrm = false; } urlText = sb.toString(); diff --git a/OsmAnd/src/net/osmand/access/NavigationInfo.java b/OsmAnd/src/net/osmand/access/NavigationInfo.java index 3e087e27ae..edd296b38a 100644 --- a/OsmAnd/src/net/osmand/access/NavigationInfo.java +++ b/OsmAnd/src/net/osmand/access/NavigationInfo.java @@ -373,7 +373,7 @@ public class NavigationInfo implements OsmAndCompassListener, OsmAndLocationList dialog.cancel(); } }); - info.setItems(attributes.toArray(new String[attributes.size()]), new DialogInterface.OnClickListener() { + info.setItems(attributes.toArray(new String[0]), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } diff --git a/OsmAnd/src/net/osmand/plus/AnalyticsHelper.java b/OsmAnd/src/net/osmand/plus/AnalyticsHelper.java index e906d7b9bb..2fd12a11ac 100644 --- a/OsmAnd/src/net/osmand/plus/AnalyticsHelper.java +++ b/OsmAnd/src/net/osmand/plus/AnalyticsHelper.java @@ -27,7 +27,7 @@ public class AnalyticsHelper extends SQLiteOpenHelper { private final static Log LOG = PlatformUtil.getLog(AnalyticsHelper.class); - private final static String ANALYTICS_UPLOAD_URL = "https://test.osmand.net/api/submit_analytics"; + private final static String ANALYTICS_UPLOAD_URL = "https://osmand.net/api/submit_analytics"; private final static String ANALYTICS_FILE_NAME = "analytics.json"; private final static int DATA_PARCEL_SIZE = 500; // 500 events diff --git a/OsmAnd/src/net/osmand/plus/AppVersionUpgradeOnInit.java b/OsmAnd/src/net/osmand/plus/AppVersionUpgradeOnInit.java index 9eeec4542b..1a80997ab3 100644 --- a/OsmAnd/src/net/osmand/plus/AppVersionUpgradeOnInit.java +++ b/OsmAnd/src/net/osmand/plus/AppVersionUpgradeOnInit.java @@ -190,14 +190,15 @@ class AppVersionUpgradeOnInit { migrateEnumPreferences(); SharedPreferences globalSharedPreferences = (SharedPreferences) settings.getGlobalPreferences(); Map globalPrefsMap = globalSharedPreferences.getAll(); - for (String key : globalPrefsMap.keySet()) { + for (Map.Entry entry : globalPrefsMap.entrySet()) { + String key = entry.getKey(); OsmandPreference pref = settings.getPreference(key); if (pref instanceof CommonPreference) { CommonPreference commonPreference = (CommonPreference) pref; if (!commonPreference.isGlobal()) { for (ApplicationMode mode : ApplicationMode.allPossibleValues()) { if (!commonPreference.isSetForMode(mode) && !commonPreference.hasDefaultValueForMode(mode)) { - settings.setPreference(key, globalPrefsMap.get(key), mode); + settings.setPreference(key, entry.getValue(), mode); } } } @@ -205,12 +206,13 @@ class AppVersionUpgradeOnInit { } SharedPreferences defaultProfilePreferences = (SharedPreferences) settings.getProfilePreferences(ApplicationMode.DEFAULT); Map defaultPrefsMap = defaultProfilePreferences.getAll(); - for (String key : defaultPrefsMap.keySet()) { + for (Map.Entry entry : defaultPrefsMap.entrySet()) { + String key = entry.getKey(); OsmandPreference pref = settings.getPreference(key); if (pref instanceof CommonPreference) { CommonPreference commonPreference = (CommonPreference) pref; if (commonPreference.isGlobal() && !commonPreference.isSet()) { - settings.setPreference(key, defaultPrefsMap.get(key)); + settings.setPreference(key, entry.getValue()); } } } diff --git a/OsmAnd/src/net/osmand/plus/ContextMenuAdapter.java b/OsmAnd/src/net/osmand/plus/ContextMenuAdapter.java index d85d6ddd68..d188a7d0ee 100644 --- a/OsmAnd/src/net/osmand/plus/ContextMenuAdapter.java +++ b/OsmAnd/src/net/osmand/plus/ContextMenuAdapter.java @@ -208,7 +208,7 @@ public class ContextMenuAdapter { } items.removeAll(itemsToRemove); return new ContextMenuArrayAdapter(activity, layoutId, R.id.title, - items.toArray(new ContextMenuItem[items.size()]), app, lightTheme, changeAppModeListener); + items.toArray(new ContextMenuItem[0]), app, lightTheme, changeAppModeListener); } public class ContextMenuArrayAdapter extends ArrayAdapter { @@ -643,7 +643,7 @@ public class ContextMenuAdapter { } public static OnItemDeleteAction makeDeleteAction(final List prefs) { - return makeDeleteAction(prefs.toArray(new OsmandPreference[prefs.size()])); + return makeDeleteAction(prefs.toArray(new OsmandPreference[0])); } private static void resetSetting(ApplicationMode appMode, OsmandPreference preference, boolean profileOnly) { diff --git a/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java b/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java index c1db6114bc..992a0e42c6 100644 --- a/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java @@ -261,10 +261,11 @@ public class FavouritesDbHelper { private boolean merge(Map source, Map destination) { boolean changed = false; - for (String ks : source.keySet()) { + for (Map.Entry entry : source.entrySet()) { + String ks = entry.getKey(); if (!destination.containsKey(ks)) { changed = true; - destination.put(ks, source.get(ks)); + destination.put(ks, entry.getValue()); } } return changed; @@ -360,7 +361,7 @@ public class FavouritesDbHelper { } public boolean addFavourite(FavouritePoint p, boolean saveImmediately) { - if (p.getName().equals("") && flatGroups.containsKey(p.getCategory())) { + if (p.getName().isEmpty() && flatGroups.containsKey(p.getCategory())) { return true; } if (!p.isAddressSpecified()) { @@ -369,7 +370,7 @@ public class FavouritesDbHelper { context.getSettings().SHOW_FAVORITES.set(true); FavoriteGroup group = getOrCreateGroup(p, 0); - if (!p.getName().equals("")) { + if (!p.getName().isEmpty()) { p.setVisible(group.visible); if (FavouritePoint.SpecialPointType.PARKING.equals(p.getSpecialPointType())) { p.setColor(ContextCompat.getColor(context, R.color.parking_icon_background)); @@ -712,9 +713,10 @@ public class FavouritesDbHelper { public boolean isGroupVisible(String name) { String nameLowercase = name.toLowerCase(); - for (String groupName : flatGroups.keySet()) { + for (Map.Entry entry : flatGroups.entrySet()) { + String groupName = entry.getKey(); if (groupName.toLowerCase().equals(nameLowercase) || FavoriteGroup.getDisplayName(context, groupName).equals(name)) { - return flatGroups.get(groupName).isVisible(); + return entry.getValue().isVisible(); } } return false; @@ -968,7 +970,7 @@ public class FavouritesDbHelper { p.setName(name); p.setCategory(cat); FavoriteGroup group = getOrCreateGroup(p, 0); - if (!name.equals("")) { + if (!name.isEmpty()) { p.setLatitude(query.getDouble(2)); p.setLongitude(query.getDouble(3)); group.points.add(p); @@ -1012,7 +1014,7 @@ public class FavouritesDbHelper { public boolean addFavouriteDB(FavouritePoint p) { - if (p.getName().equals("") && flatGroups.containsKey(p.getCategory())) { + if (p.getName().isEmpty() && flatGroups.containsKey(p.getCategory())) { return true; } SQLiteConnection db = openConnection(false); @@ -1022,7 +1024,7 @@ public class FavouritesDbHelper { "INSERT INTO " + FAVOURITE_TABLE_NAME + " (" + FAVOURITE_COL_NAME + ", " + FAVOURITE_COL_CATEGORY + ", " + FAVOURITE_COL_LAT + ", " + FAVOURITE_COL_LON + ")" + " VALUES (?, ?, ?, ?)", new Object[]{p.getName(), p.getCategory(), p.getLatitude(), p.getLongitude()}); //$NON-NLS-1$ //$NON-NLS-2$ FavoriteGroup group = getOrCreateGroup(p, 0); - if (!p.getName().equals("")) { + if (!p.getName().isEmpty()) { p.setVisible(group.visible); p.setColor(group.color); group.points.add(p); diff --git a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java index 2651e7b988..026987d13b 100644 --- a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java @@ -408,10 +408,10 @@ public class GpxSelectionHelper { boolean split = true; if (group.splitDistance > 0) { List trackSegments = r.splitByDistance(group.splitDistance, joinSegments); - as = trackSegments.toArray(new GPXTrackAnalysis[trackSegments.size()]); + as = trackSegments.toArray(new GPXTrackAnalysis[0]); } else if (group.splitTime > 0) { List trackSegments = r.splitByTime(group.splitTime, joinSegments); - as = trackSegments.toArray(new GPXTrackAnalysis[trackSegments.size()]); + as = trackSegments.toArray(new GPXTrackAnalysis[0]); } else { split = false; as = new GPXTrackAnalysis[] {GPXTrackAnalysis.segment(0, r)}; diff --git a/OsmAnd/src/net/osmand/plus/OsmAndConstants.java b/OsmAnd/src/net/osmand/plus/OsmAndConstants.java index 4e808ac947..aee7b58bfa 100644 --- a/OsmAnd/src/net/osmand/plus/OsmAndConstants.java +++ b/OsmAnd/src/net/osmand/plus/OsmAndConstants.java @@ -1,16 +1,16 @@ package net.osmand.plus; public interface OsmAndConstants { - - + + public int UI_HANDLER_MAP_VIEW = 3000; - + public int UI_HANDLER_MAP_CONTROLS = 4000; - + public int UI_HANDLER_LOCATION_SERVICE = 5000; public int UI_HANDLER_PROGRESS = 6000; public int UI_HANDLER_SEARCH = 7000; - + } diff --git a/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java b/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java index f9d3315bf5..3fd1aa1adc 100644 --- a/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java +++ b/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java @@ -14,11 +14,11 @@ import net.osmand.osm.AbstractPoiType; import net.osmand.osm.MapPoiTypes; import net.osmand.osm.PoiCategory; import net.osmand.osm.PoiType; -import net.osmand.plus.settings.backend.ApplicationMode; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.helpers.enums.AngularConstants; import net.osmand.plus.helpers.enums.MetricsConstants; import net.osmand.plus.helpers.enums.SpeedConstants; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.util.Algorithms; import java.text.DateFormatSymbols; @@ -30,7 +30,6 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Locale; -import java.util.Map.Entry; import static net.osmand.data.PointDescription.getLocationOlcName; @@ -64,7 +63,7 @@ public class OsmAndFormatter { private static final char WEST = 'W'; private static final char EAST = 'E'; - { + static { fixed2.setMinimumFractionDigits(2); fixed1.setMinimumFractionDigits(1); fixed1.setMinimumIntegerDigits(1); @@ -417,7 +416,7 @@ public class OsmAndFormatter { String typeName = amenity.getSubType(); if (pt != null) { typeName = pt.getTranslation(); - } else if(typeName != null){ + } else if (typeName != null) { typeName = Algorithms.capitalizeFirstLetterAndLowercase(typeName.replace('_', ' ')); } List res = new ArrayList<>(); @@ -426,7 +425,7 @@ public class OsmAndFormatter { for (String name : amenity.getAllNames(true)) { addPoiString(typeName, name, res); } - for (String name : amenity.getAdditionalInfo().values()) { + for (String name : amenity.getAdditionalInfoValues(false)) { addPoiString(typeName, name, res); } return res; @@ -444,36 +443,34 @@ public class OsmAndFormatter { public static String getAmenityDescriptionContent(OsmandApplication ctx, Amenity amenity, boolean shortDescription) { StringBuilder d = new StringBuilder(); - if(amenity.getType().isWiki()) { + if (amenity.getType().isWiki()) { return ""; } MapPoiTypes poiTypes = ctx.getPoiTypes(); - for(Entry e : amenity.getAdditionalInfo().entrySet()) { - String key = e.getKey(); - String vl = e.getValue(); - if(key.startsWith("name:")) { + for (String key : amenity.getAdditionalInfoKeys()) { + String vl = amenity.getAdditionalInfo(key); + if (key.startsWith("name:")) { continue; - } else if(vl.length() >= 150) { - if(shortDescription) { + } else if (vl.length() >= 150) { + if (shortDescription) { continue; } - } else if(Amenity.OPENING_HOURS.equals(key)) { + } else if (Amenity.OPENING_HOURS.equals(key)) { d.append(ctx.getString(R.string.opening_hours) + ": "); - } else if(Amenity.PHONE.equals(key)) { + } else if (Amenity.PHONE.equals(key)) { d.append(ctx.getString(R.string.phone) + ": "); - } else if(Amenity.WEBSITE.equals(key)) { + } else if (Amenity.WEBSITE.equals(key)) { d.append(ctx.getString(R.string.website) + ": "); } else { - AbstractPoiType pt = poiTypes.getAnyPoiAdditionalTypeByKey(e.getKey()); + AbstractPoiType pt = poiTypes.getAnyPoiAdditionalTypeByKey(key); if (pt != null) { - if(pt instanceof PoiType && !((PoiType) pt).isText()) { + if (pt instanceof PoiType && !((PoiType) pt).isText()) { vl = pt.getTranslation(); } else { - vl = pt.getTranslation() + ": " + amenity.unzipContent(e.getValue()); + vl = pt.getTranslation() + ": " + vl; } } else { - vl = Algorithms.capitalizeFirstLetterAndLowercase(e.getKey()) + - ": " + amenity.unzipContent(e.getValue()); + vl = Algorithms.capitalizeFirstLetterAndLowercase(key) + ": " + vl; } } d.append(vl).append('\n'); diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index 233350b319..bbe45aab51 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -412,8 +412,8 @@ public class OsmandApplication extends MultiDexApplication { if (defaultLocale == null) { defaultLocale = Locale.getDefault(); } - if (!"".equals(lang)) { - if (!"".equals(country)) { + if (!Algorithms.isEmpty(lang)) { + if (!Algorithms.isEmpty(country)) { preferredLocale = new Locale(lang, country); } else { preferredLocale = new Locale(lang); @@ -421,9 +421,9 @@ public class OsmandApplication extends MultiDexApplication { } Locale selectedLocale = null; - if (!"".equals(lang) && !config.locale.equals(preferredLocale)) { + if (!Algorithms.isEmpty(lang) && !config.locale.equals(preferredLocale)) { selectedLocale = preferredLocale; - } else if ("".equals(lang) && defaultLocale != null && Locale.getDefault() != defaultLocale) { + } else if (Algorithms.isEmpty(lang) && defaultLocale != null && Locale.getDefault() != defaultLocale) { selectedLocale = defaultLocale; preferredLocale = null; } @@ -807,17 +807,17 @@ public class OsmandApplication extends MultiDexApplication { } return s; } - + public void setLanguage(Context context) { if (preferredLocale != null) { Configuration config = context.getResources().getConfiguration(); String lang = preferredLocale.getLanguage(); - if (!"".equals(lang) && !config.locale.getLanguage().equals(lang)) { + if (!Algorithms.isEmpty(lang) && !config.locale.getLanguage().equals(lang)) { preferredLocale = new Locale(lang); Locale.setDefault(preferredLocale); config.locale = preferredLocale; context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics()); - } else if("".equals(lang) && defaultLocale != null && Locale.getDefault() != defaultLocale) { + } else if (Algorithms.isEmpty(lang) && defaultLocale != null && Locale.getDefault() != defaultLocale) { Locale.setDefault(defaultLocale); config.locale = defaultLocale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); diff --git a/OsmAnd/src/net/osmand/plus/TargetPointsHelper.java b/OsmAnd/src/net/osmand/plus/TargetPointsHelper.java index 07ef8df985..4221ffa308 100644 --- a/OsmAnd/src/net/osmand/plus/TargetPointsHelper.java +++ b/OsmAnd/src/net/osmand/plus/TargetPointsHelper.java @@ -309,9 +309,7 @@ public class TargetPointsHelper { public List getIntermediatePointsNavigation() { List intermediatePoints = new ArrayList<>(); if (settings.USE_INTERMEDIATE_POINTS_NAVIGATION.get()) { - for (TargetPoint t : this.intermediatePoints) { - intermediatePoints.add(t); - } + intermediatePoints.addAll(this.intermediatePoints); } return intermediatePoints; } @@ -347,8 +345,7 @@ public class TargetPointsHelper { } public List getIntermediatePointsWithTarget() { - List res = new ArrayList<>(); - res.addAll(this.intermediatePoints); + List res = new ArrayList<>(this.intermediatePoints); if(pointToNavigate != null) { res.add(pointToNavigate); } diff --git a/OsmAnd/src/net/osmand/plus/activities/HelpActivity.java b/OsmAnd/src/net/osmand/plus/activities/HelpActivity.java index b7b3044f97..7eb21d4ee8 100644 --- a/OsmAnd/src/net/osmand/plus/activities/HelpActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/HelpActivity.java @@ -176,7 +176,7 @@ public class HelpActivity extends OsmandActionBarActivity implements AdapterView "feature_articles/osmand-3-8-released.html")); String releasedate = ""; - if (!this.getString(R.string.app_edition).equals("")) { + if (!this.getString(R.string.app_edition).isEmpty()) { releasedate = ", " + this.getString(R.string.shared_string_release).toLowerCase() + ": " + this.getString(R.string.app_edition); } String version = Version.getFullVersion(getMyApplication()) + releasedate; diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index 9dfe4f46d1..313fa6b917 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -304,9 +304,6 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven } mapActions = new MapActivityActions(this); mapLayers = new MapActivityLayers(this); - if (mapViewTrackingUtilities == null) { - mapViewTrackingUtilities = new MapViewTrackingUtilities(app); - } dashboardOnMap.createDashboardView(); checkAppInitialization(); diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java index 1a9c28a689..00bd656b63 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java @@ -1149,7 +1149,7 @@ public class MapActivityActions implements DialogProvider { items.add(getString(R.string.show_location)); items.add(getString(R.string.shared_string_show_details)); AlertDialog.Builder menu = new AlertDialog.Builder(mapActivity); - menu.setItems(items.toArray(new String[items.size()]), new DialogInterface.OnClickListener() { + menu.setItems(items.toArray(new String[0]), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int item) { dialog.dismiss(); diff --git a/OsmAnd/src/net/osmand/plus/activities/SavingTrackHelper.java b/OsmAnd/src/net/osmand/plus/activities/SavingTrackHelper.java index 5bf6c2b0a1..ff7039702e 100644 --- a/OsmAnd/src/net/osmand/plus/activities/SavingTrackHelper.java +++ b/OsmAnd/src/net/osmand/plus/activities/SavingTrackHelper.java @@ -208,11 +208,13 @@ public class SavingTrackHelper extends SQLiteOpenHelper { Map data = collectRecordedData(); // save file - for (final String f : data.keySet()) { + for (final Map.Entry entry : data.entrySet()) { + final String f = entry.getKey(); + GPXFile gpx = entry.getValue(); log.debug("Filename: " + f); File fout = new File(dir, f + IndexConstants.GPX_FILE_EXT); - if (!data.get(f).isEmpty()) { - WptPt pt = data.get(f).findPointToShow(); + if (!gpx.isEmpty()) { + WptPt pt = gpx.findPointToShow(); String fileName = f + "_" + new SimpleDateFormat("HH-mm_EEE", Locale.US).format(new Date(pt.time)); //$NON-NLS-1$ Integer trackStorageDirectory = ctx.getSettings().TRACK_STORAGE_DIRECTORY.get(); if (!OsmandSettings.REC_DIRECTORY.equals(trackStorageDirectory)) { @@ -235,13 +237,12 @@ public class SavingTrackHelper extends SQLiteOpenHelper { } } - Exception warn = GPXUtilities.writeGpxFile(fout, data.get(f)); + Exception warn = GPXUtilities.writeGpxFile(fout, gpx); if (warn != null) { warnings.add(warn.getMessage()); return new SaveGpxResult(warnings, new ArrayList()); } - GPXFile gpx = data.get(f); GPXTrackAnalysis analysis = gpx.getAnalysis(fout.lastModified()); GpxDataItem item = new GpxDataItem(fout, analysis); ctx.getGpxDbHelper().add(item); diff --git a/OsmAnd/src/net/osmand/plus/activities/actions/StartGPSStatus.java b/OsmAnd/src/net/osmand/plus/activities/actions/StartGPSStatus.java index 0c64258825..79abd4190a 100644 --- a/OsmAnd/src/net/osmand/plus/activities/actions/StartGPSStatus.java +++ b/OsmAnd/src/net/osmand/plus/activities/actions/StartGPSStatus.java @@ -165,7 +165,7 @@ public class StartGPSStatus extends OsmAndAction { // if (g.activity.length() == 0) { PackageManager pm = mapActivity.getPackageManager(); try { - String appName = !g.paidAppName.equals("") && + String appName = !g.paidAppName.isEmpty() && g.installed(mapActivity, g.paidAppName) ? g.paidAppName : g.appName; intent = pm.getLaunchIntentForPackage(appName); } catch (RuntimeException e) { diff --git a/OsmAnd/src/net/osmand/plus/activities/search/SearchPoiFilterFragment.java b/OsmAnd/src/net/osmand/plus/activities/search/SearchPoiFilterFragment.java index a1c4d466e1..6b3de30970 100644 --- a/OsmAnd/src/net/osmand/plus/activities/search/SearchPoiFilterFragment.java +++ b/OsmAnd/src/net/osmand/plus/activities/search/SearchPoiFilterFragment.java @@ -166,9 +166,7 @@ public class SearchPoiFilterFragment extends OsmAndListFragment implements Searc } }); - for (AbstractPoiType p : res) { - filters.add(p); - } + filters.addAll(res); filters.add(poiFilters.getSearchByNamePOIFilter()); if (OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class) != null) { filters.add(poiFilters.getNominatimPOIFilter()); diff --git a/OsmAnd/src/net/osmand/plus/api/FileSettingsAPIImpl.java b/OsmAnd/src/net/osmand/plus/api/FileSettingsAPIImpl.java index 6a8b8a1b06..ab30a9a102 100644 --- a/OsmAnd/src/net/osmand/plus/api/FileSettingsAPIImpl.java +++ b/OsmAnd/src/net/osmand/plus/api/FileSettingsAPIImpl.java @@ -25,9 +25,9 @@ public class FileSettingsAPIImpl implements SettingsAPI { Properties props = new Properties(); FileInputStream fis = new FileInputStream(file); props.load(fis); - for (Object key : props.keySet()) { - String k = key.toString(); - map.put(k, props.get(key)); + for (Entry entry : props.entrySet()) { + String k = entry.getKey().toString(); + map.put(k, entry.getValue()); } } } diff --git a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java index b8d4ef0c92..c42e4de8aa 100644 --- a/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java +++ b/OsmAnd/src/net/osmand/plus/audionotes/AudioVideoNotesPlugin.java @@ -819,7 +819,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { } } }); - mapInfoLayer.registerSideWidget(recordControl, new AudioVideoNotesWidgetState(app), "audionotes", false, 32); + mapInfoLayer.registerSideWidget(recordControl, new AudioVideoNotesWidgetState(app, AV_DEFAULT_ACTION), "audionotes", false, 32); mapInfoLayer.recreateControls(); } } @@ -930,11 +930,21 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { stopRecording(activity, false); } + @Override + public void mapActivityResume(MapActivity activity) { + this.mapActivity = activity; + if (Build.VERSION.SDK_INT < 29) { + runAction(activity); + } + } + @Override public void mapActivityResumeOnTop(MapActivity activity) { this.mapActivity = activity; -// ((AudioManager) activity.getSystemService(Context.AUDIO_SERVICE)).registerMediaButtonEventReceiver( -// new ComponentName(activity, MediaRemoteControlReceiver.class)); + runAction(activity); + } + + private void runAction(MapActivity activity) { if (runAction != -1) { takeAction(activity, actionLon, actionLat, runAction); runAction = -1; @@ -1860,7 +1870,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { protected Recording[] getRecordingsSorted() { checkRecordings(); Collection allObjects = getAllRecordings(); - Recording[] res = allObjects.toArray(new Recording[allObjects.size()]); + Recording[] res = allObjects.toArray(new Recording[0]); Arrays.sort(res, new Comparator() { @Override @@ -2153,20 +2163,23 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { return DashAudioVideoNotesFragment.FRAGMENT_DATA; } - public class AudioVideoNotesWidgetState extends WidgetState { + public static class AudioVideoNotesWidgetState extends WidgetState { + + private final CommonPreference defaultActionSetting; private static final int AV_WIDGET_STATE_ASK = R.id.av_notes_widget_state_ask; private static final int AV_WIDGET_STATE_AUDIO = R.id.av_notes_widget_state_audio; private static final int AV_WIDGET_STATE_VIDEO = R.id.av_notes_widget_state_video; private static final int AV_WIDGET_STATE_PHOTO = R.id.av_notes_widget_state_photo; - AudioVideoNotesWidgetState(OsmandApplication ctx) { + AudioVideoNotesWidgetState(OsmandApplication ctx, CommonPreference defaultActionSetting) { super(ctx); + this.defaultActionSetting = defaultActionSetting; } @Override public int getMenuTitleId() { - Integer action = AV_DEFAULT_ACTION.get(); + Integer action = defaultActionSetting.get(); switch (action) { case AV_DEFAULT_ACTION_AUDIO: return R.string.av_def_action_audio; @@ -2181,7 +2194,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { @Override public int getMenuIconId() { - Integer action = AV_DEFAULT_ACTION.get(); + Integer action = defaultActionSetting.get(); switch (action) { case AV_DEFAULT_ACTION_AUDIO: return R.drawable.ic_action_micro_dark; @@ -2196,7 +2209,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { @Override public int getMenuItemId() { - Integer action = AV_DEFAULT_ACTION.get(); + Integer action = defaultActionSetting.get(); switch (action) { case AV_DEFAULT_ACTION_AUDIO: return AV_WIDGET_STATE_AUDIO; @@ -2226,19 +2239,14 @@ public class AudioVideoNotesPlugin extends OsmandPlugin { @Override public void changeState(int stateId) { - switch (stateId) { - case AV_WIDGET_STATE_AUDIO: - AV_DEFAULT_ACTION.set(AV_DEFAULT_ACTION_AUDIO); - break; - case AV_WIDGET_STATE_VIDEO: - AV_DEFAULT_ACTION.set(AV_DEFAULT_ACTION_VIDEO); - break; - case AV_WIDGET_STATE_PHOTO: - AV_DEFAULT_ACTION.set(AV_DEFAULT_ACTION_TAKEPICTURE); - break; - default: - AV_DEFAULT_ACTION.set(AV_DEFAULT_ACTION_CHOOSE); - break; + if (stateId == AV_WIDGET_STATE_AUDIO) { + defaultActionSetting.set(AV_DEFAULT_ACTION_AUDIO); + } else if (stateId == AV_WIDGET_STATE_VIDEO) { + defaultActionSetting.set(AV_DEFAULT_ACTION_VIDEO); + } else if (stateId == AV_WIDGET_STATE_PHOTO) { + defaultActionSetting.set(AV_DEFAULT_ACTION_TAKEPICTURE); + } else { + defaultActionSetting.set(AV_DEFAULT_ACTION_CHOOSE); } } } diff --git a/OsmAnd/src/net/osmand/plus/dashboard/DashChooseAppDirFragment.java b/OsmAnd/src/net/osmand/plus/dashboard/DashChooseAppDirFragment.java index 883010ea46..e976d0b4ea 100644 --- a/OsmAnd/src/net/osmand/plus/dashboard/DashChooseAppDirFragment.java +++ b/OsmAnd/src/net/osmand/plus/dashboard/DashChooseAppDirFragment.java @@ -223,7 +223,7 @@ public class DashChooseAppDirFragment { paths.add(""); types.add(OsmandSettings.EXTERNAL_STORAGE_TYPE_SPECIFIED); - editalert.setSingleChoiceItems(items.toArray(new String[items.size()]), selected, + editalert.setSingleChoiceItems(items.toArray(new String[0]), selected, new DialogInterface.OnClickListener() { @Override diff --git a/OsmAnd/src/net/osmand/plus/development/LogcatActivity.java b/OsmAnd/src/net/osmand/plus/development/LogcatActivity.java index 20f5c4ba4a..af0f6bbbfd 100644 --- a/OsmAnd/src/net/osmand/plus/development/LogcatActivity.java +++ b/OsmAnd/src/net/osmand/plus/development/LogcatActivity.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -298,9 +299,7 @@ public class LogcatActivity extends ActionBarProgressActivity { LogcatActivity activity = logcatActivity.get(); if (activity != null) { boolean autoscroll = !activity.recyclerView.canScrollVertically(1); - for(String s : values) { - activity.logs.add(s); - } + activity.logs.addAll(Arrays.asList(values)); activity.adapter.notifyDataSetChanged(); if(autoscroll) { activity.recyclerView.scrollToPosition(activity.logs.size() - 1); diff --git a/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java b/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java index d7798a646b..e5d7b3e11d 100644 --- a/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java +++ b/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java @@ -140,4 +140,13 @@ public class OsmandDevelopmentPlugin extends OsmandPlugin { public DashFragmentData getCardFragment() { return DashSimulateFragment.FRAGMENT_DATA; } + + @Override + public void disable(OsmandApplication app) { + if (app.getSettings().USE_DEV_URL.get()) { + app.getSettings().USE_DEV_URL.set(false); + app.getOsmOAuthHelper().resetAuthorization(); + } + super.disable(app); + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/dialogs/ConfigureMapMenu.java b/OsmAnd/src/net/osmand/plus/dialogs/ConfigureMapMenu.java index 858f80e018..ca7382dd6e 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/ConfigureMapMenu.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/ConfigureMapMenu.java @@ -404,7 +404,7 @@ public class ConfigureMapMenu { bld.setTitle(R.string.map_magnifier); bld.setNegativeButton(R.string.shared_string_dismiss, null); DialogListItemAdapter dialogAdapter = DialogListItemAdapter.createSingleChoiceAdapter( - values.toArray(new String[values.size()]), nightMode, i, app, selectedProfileColor, themeRes, new View.OnClickListener() { + values.toArray(new String[0]), nightMode, i, app, selectedProfileColor, themeRes, new View.OnClickListener() { @Override public void onClick(View v) { int which = (int) v.getTag(); @@ -481,7 +481,7 @@ public class ConfigureMapMenu { .createItem()); String localeDescr = activity.getMyApplication().getSettings().MAP_PREFERRED_LOCALE.get(); - localeDescr = localeDescr == null || localeDescr.equals("") ? activity.getString(R.string.local_map_names) + localeDescr = localeDescr == null || localeDescr.isEmpty() ? activity.getString(R.string.local_map_names) : localeDescr; adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_locale, activity) .setId(MAP_LANGUAGE_ID) @@ -570,7 +570,7 @@ public class ConfigureMapMenu { txtIds[index]); refreshMapComplete(activity); String localeDescr = txtIds[index]; - localeDescr = localeDescr == null || localeDescr.equals("") ? activity + localeDescr = localeDescr == null || localeDescr.isEmpty() ? activity .getString(R.string.local_map_names) : localeDescr; adapter.getItem(pos).setDescription(localeDescr); ad.notifyDataSetInvalidated(); @@ -639,7 +639,7 @@ public class ConfigureMapMenu { return mp.get(lhs).compareTo(mp.get(rhs)); } }); - return lst.toArray(new String[lst.size()]); + return lst.toArray(new String[0]); } public static String[] getMapNamesValues(Context ctx, String[] ids) { diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadFileHelper.java b/OsmAnd/src/net/osmand/plus/download/DownloadFileHelper.java index 36d2f21b85..c85d63361a 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadFileHelper.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadFileHelper.java @@ -349,7 +349,7 @@ public class DownloadFileHelper { private int currentRead = 0; public CountingMultiInputStream(List streams) { - this.delegate = streams.toArray(new InputStream[streams.size()]); + this.delegate = streams.toArray(new InputStream[0]); } @Override diff --git a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java index 4cf4f1154a..9160160973 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java @@ -582,7 +582,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement operationTask = null; } if (operationTask != null) { - operationTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, selectedItems.toArray(new LocalIndexInfo[selectedItems.size()])); + operationTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, selectedItems.toArray(new LocalIndexInfo[0])); } if (actionMode != null) { actionMode.finish(); diff --git a/OsmAnd/src/net/osmand/plus/download/ui/UpdatesIndexFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/UpdatesIndexFragment.java index 65baa93718..f7362edc76 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/UpdatesIndexFragment.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/UpdatesIndexFragment.java @@ -166,12 +166,12 @@ public class UpdatesIndexFragment extends OsmAndListFragment implements Download dialog.setPositiveButton(R.string.shared_string_update, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - getMyActivity().startDownload(indexItems.toArray(new IndexItem[indexItems.size()])); + getMyActivity().startDownload(indexItems.toArray(new IndexItem[0])); } }); dialog.create().show(); } else { - getMyActivity().startDownload(indexItems.toArray(new IndexItem[indexItems.size()])); + getMyActivity().startDownload(indexItems.toArray(new IndexItem[0])); } } }); diff --git a/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java index 6222663a00..da5f6359b0 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java @@ -871,7 +871,7 @@ public class ExternalApiHelper { searchTypes.add(HOUSE); searchTypes.add(STREET_INTERSECTION); } - searchSettings = searchSettings.setSearchTypes(searchTypes.toArray(new ObjectType[searchTypes.size()])); + searchSettings = searchSettings.setSearchTypes(searchTypes.toArray(new ObjectType[0])); core.search(searchQuery, false, null, searchSettings); } diff --git a/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java b/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java index 5fa07a91e3..a7d6dd7f79 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java @@ -297,12 +297,8 @@ public class IntentHelper { Uri uri = intent.getData(); if (uri.toString().startsWith("osmand-oauth")) { String oauthVerifier = uri.getQueryParameter("oauth_verifier"); + app.getOsmOAuthHelper().addListener(getOnAuthorizeListener()); app.getOsmOAuthHelper().authorize(oauthVerifier); - for (Fragment fragment : mapActivity.getSupportFragmentManager().getFragments()) { - if (fragment instanceof OsmAuthorizationListener) { - ((OsmAuthorizationListener) fragment).authorizationCompleted(); - } - } mapActivity.setIntent(null); return true; } @@ -310,6 +306,19 @@ public class IntentHelper { return false; } + private OsmAuthorizationListener getOnAuthorizeListener() { + return new OsmAuthorizationListener() { + @Override + public void authorizationCompleted() { + for (Fragment fragment : mapActivity.getSupportFragmentManager().getFragments()) { + if (fragment instanceof OsmAuthorizationListener) { + ((OsmAuthorizationListener) fragment).authorizationCompleted(); + } + } + } + }; + } + private boolean handleSendText(Intent intent) { String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); if (!Algorithms.isEmpty(sharedText)) { diff --git a/OsmAnd/src/net/osmand/plus/helpers/MapMarkerDialogHelper.java b/OsmAnd/src/net/osmand/plus/helpers/MapMarkerDialogHelper.java index a90247e644..ab40f14407 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/MapMarkerDialogHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/MapMarkerDialogHelper.java @@ -101,7 +101,7 @@ public class MapMarkerDialogHelper { String desc = OsmAndFormatter.getFormattedDate(app, marker.creationDate); String markerGroupName = marker.groupName; if (markerGroupName != null) { - if (markerGroupName.equals("")) { + if (markerGroupName.isEmpty()) { markerGroupName = app.getString(R.string.shared_string_favorites); } desc += " • " + markerGroupName; diff --git a/OsmAnd/src/net/osmand/plus/helpers/SearchHistoryHelper.java b/OsmAnd/src/net/osmand/plus/helpers/SearchHistoryHelper.java index 0f4af1f68d..693227f434 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/SearchHistoryHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/SearchHistoryHelper.java @@ -376,7 +376,10 @@ public class SearchHistoryHelper { SQLiteConnection db = openConnection(false); if (db != null) { try { - removeQuery(e.getSerializedName(), db); + db.execSQL("DELETE FROM " + HISTORY_TABLE_NAME + " WHERE " + + HISTORY_COL_NAME + " = ? AND " + + HISTORY_COL_LAT + " = ? AND " + HISTORY_COL_LON + " = ?", + new Object[] {e.getSerializedName(), e.getLat(), e.getLon()}); } finally { db.close(); } @@ -385,11 +388,6 @@ public class SearchHistoryHelper { return false; } - private void removeQuery(String name, SQLiteConnection db) { - db.execSQL("DELETE FROM " + HISTORY_TABLE_NAME + " WHERE " + HISTORY_COL_NAME + " = ?", - new Object[]{name}); - } - public boolean removeAll() { SQLiteConnection db = openConnection(false); if (db != null) { @@ -411,9 +409,10 @@ public class SearchHistoryHelper { "UPDATE " + HISTORY_TABLE_NAME + " SET " + HISTORY_COL_TIME + "= ? " + ", " + HISTORY_COL_FREQ_INTERVALS + " = ? " + ", " + HISTORY_COL_FREQ_VALUES + "= ? WHERE " + - HISTORY_COL_NAME + " = ?", - new Object[]{e.getLastAccessTime(), e.getIntervals(), e.getIntervalsValues(), - e.getSerializedName()}); + HISTORY_COL_NAME + " = ? AND " + + HISTORY_COL_LAT + " = ? AND " + HISTORY_COL_LON + " = ?", + new Object[] {e.getLastAccessTime(), e.getIntervals(), e.getIntervalsValues(), + e.getSerializedName(), e.getLat(), e.getLon()}); } finally { db.close(); } diff --git a/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java b/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java index 16fb083f13..09d2064284 100644 --- a/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java @@ -513,10 +513,9 @@ public class ImportHelper { private File getFileToSave(final String fileName, final File importDir, final WptPt pt) { final StringBuilder builder = new StringBuilder(fileName); - if ("".equals(fileName)) { + if (Algorithms.isEmpty(fileName)) { builder.append("import_").append(new SimpleDateFormat("HH-mm_EEE", Locale.US).format(new Date(pt.time))).append(GPX_FILE_EXT); //$NON-NLS-1$ - } - if (fileName.endsWith(KML_SUFFIX)) { + } else if (fileName.endsWith(KML_SUFFIX)) { builder.replace(builder.length() - KML_SUFFIX.length(), builder.length(), GPX_FILE_EXT); } else if (fileName.endsWith(KMZ_SUFFIX)) { builder.replace(builder.length() - KMZ_SUFFIX.length(), builder.length(), GPX_FILE_EXT); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java index 1aa35b8589..a39259a9e4 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java @@ -6,13 +6,16 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.PorterDuff; -import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.net.Uri; import android.os.AsyncTask; +import android.os.Handler; +import android.os.Looper; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -33,11 +36,14 @@ import androidx.appcompat.view.ContextThemeWrapper; import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; import net.osmand.AndroidUtils; +import net.osmand.PlatformUtil; import net.osmand.data.Amenity; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; +import net.osmand.osm.io.NetworkUtils; import net.osmand.plus.*; +import net.osmand.plus.activities.ActivityResultListener; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.FontCache; import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard; @@ -46,7 +52,10 @@ import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard; import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask; import net.osmand.plus.mapcontextmenu.builders.cards.NoImagesCard; import net.osmand.plus.mapcontextmenu.controllers.TransportStopController; +import net.osmand.plus.openplacereviews.AddPhotosBottomSheetDialogFragment; +import net.osmand.plus.openplacereviews.OPRWebviewActivity; import net.osmand.plus.openplacereviews.OprStartFragment; +import net.osmand.plus.osmedit.opr.OpenDBAPI; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.transport.TransportStopRoute; @@ -56,13 +65,21 @@ import net.osmand.plus.widgets.TextViewEx; import net.osmand.plus.widgets.tools.ClickableSpanTouchListener; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; +import org.apache.commons.logging.Log; +import org.openplacereviews.opendb.util.exception.FailedVerificationException; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.util.*; import static net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener; public class MenuBuilder { + private static final int PICK_IMAGE = 1231; + private static final Log LOG = PlatformUtil.getLog(MenuBuilder.class); public static final float SHADOW_HEIGHT_TOP_DP = 17f; public static final int TITLE_LIMIT = 60; protected static final String[] arrowChars = new String[] {"=>", " - "}; @@ -91,6 +108,35 @@ public class MenuBuilder { private String preferredMapLang; private String preferredMapAppLang; private boolean transliterateNames; + private View view; + + private final OpenDBAPI openDBAPI = new OpenDBAPI(); + private String[] placeId = new String[0]; + private GetImageCardsListener imageCardListener = new GetImageCardsListener() { + @Override + public void onPostProcess(List cardList) { + processOnlinePhotosCards(cardList); + } + + @Override + public void onPlaceIdAcquired(String[] placeId) { + MenuBuilder.this.placeId = placeId; + } + + @Override + public void onFinish(List cardList) { + if (!isHidden()) { + List cards = new ArrayList(cardList); + if (cardList.size() == 0) { + cards.add(new NoImagesCard(mapActivity)); + } + if (onlinePhotoCardsRow != null) { + onlinePhotoCardsRow.setCards(cards); + } + onlinePhotoCards = cards; + } + } + }; public interface CollapseExpandListener { void onCollapseExpand(boolean collapsed); @@ -183,6 +229,7 @@ public class MenuBuilder { } public void build(View view) { + this.view = view; firstRow = true; hidden = false; buildTopInternal(view); @@ -311,35 +358,53 @@ public class MenuBuilder { } } - private View createAddPhotoButton(Context context) { - TextView b = new TextView(context); - b.setOnClickListener(new OnClickListener() { + private View createAddPhotoButton(Context ctx) { + View view = UiUtilities.getInflater(ctx, !light).inflate(R.layout.dialog_button_with_icon, null); + int dp6 = ctx.getResources().getDimensionPixelSize(R.dimen.bottom_sheet_title_padding_bottom); + View button = view.findViewById(R.id.button); + UiUtilities.setupDialogButton(!light, button, UiUtilities.DialogButtonType.STROKED, + ctx.getString(R.string.shared_string_add_photo), R.drawable.ic_sample); + TextView textView = view.findViewById(R.id.button_text); + textView.setCompoundDrawablePadding(dp6); + button.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - OprStartFragment.showInstance(mapActivity.getSupportFragmentManager()); + if (false) { + AddPhotosBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager()); + } else { + registerResultListener(view); + final String baseUrl = OPRWebviewActivity.getBaseUrl(app); + final String name = OPRWebviewActivity.getUsernameFromCookie(app); + final String privateKey = OPRWebviewActivity.getPrivateKeyFromCookie(app); + if (privateKey == null || privateKey.isEmpty()) { + OprStartFragment.showInstance(mapActivity.getSupportFragmentManager()); + return; + } + new Thread(new Runnable() { + @Override + public void run() { + if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) { + app.runInUIThread(new Runnable() { + @Override + public void run() { + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + mapActivity.startActivityForResult(Intent.createChooser(intent, + mapActivity.getString(R.string.select_picture)), PICK_IMAGE); + } + }); + } else { + OprStartFragment.showInstance(mapActivity.getSupportFragmentManager()); + } + } + }).start(); + } } }); - b.setTypeface(FontCache.getRobotoRegular(context)); - Drawable d = ContextCompat.getDrawable(context, R.drawable.ic_sample); - b.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null); - LinearLayout.LayoutParams params = new - LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT); - int dp16 = AndroidUtils.dpToPx(context, 16f); - int dp8 = AndroidUtils.dpToPx(context, 8f); - params.setMargins(dp16, 0, dp16, dp16); - b.setPadding(dp8, dp8, dp16, dp8); - b.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); - b.setLayoutParams(params); - b.setCompoundDrawablePadding(dp8); - b.setGravity(Gravity.CENTER_VERTICAL); - b.setTypeface(null, Typeface.BOLD); - b.setText(context.getResources().getString(R.string.shared_string_add_photo)); - b.setBackgroundResource(R.drawable.btn_border_light); //TODO This feature is under development - b.setVisibility(View.GONE); - b.setTextColor(ContextCompat.getColor(context, R.color.preference_category_title)); - return b; + view.setVisibility(View.GONE); + return view; } private void buildCoordinatesRow(View view) { @@ -351,34 +416,124 @@ public class MenuBuilder { false, null, false); } + private void registerResultListener(final View view) { + mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new ActivityResultListener. + OnActivityResultListener() { + @Override + public void onResult(int resultCode, Intent resultData) { + if (resultData != null) { + handleSelectedImage(view, resultData.getData()); + } + } + })); + } + + private void handleSelectedImage(final View view, final Uri uri) { + Thread t = new Thread(new Runnable() { + @Override + public void run() { + InputStream inputStream = null; + try { + inputStream = app.getContentResolver().openInputStream(uri); + if (inputStream != null) { + uploadImageToPlace(inputStream); + } + } catch (Exception e) { + LOG.error(e); + String str = app.getString(R.string.cannot_upload_image); + showToastMessage(str); + } finally { + Algorithms.closeStream(inputStream); + } + } + }); + t.start(); + } + + private void uploadImageToPlace(InputStream image) { + InputStream serverData = new ByteArrayInputStream(compressImage(image)); + final String baseUrl = OPRWebviewActivity.getBaseUrl(app); + String url = baseUrl + "api/ipfs/image"; + String response = NetworkUtils.sendPostDataRequest(url, serverData); + if (response != null) { + int res = 0; + try { + StringBuilder error = new StringBuilder(); + res = openDBAPI.uploadImage( + placeId, + baseUrl, + OPRWebviewActivity.getPrivateKeyFromCookie(app), + OPRWebviewActivity.getUsernameFromCookie(app), + response, error); + if (res != 200) { + showToastMessage(error.toString()); + } else { + //ok, continue + } + } catch (FailedVerificationException e) { + LOG.error(e); + checkTokenAndShowScreen(); + } + if (res != 200) { + //image was uploaded but not added to blockchain + checkTokenAndShowScreen(); + } else { + String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1); + showToastMessage(str); + //refresh the image + execute(new GetImageCardsTask(mapActivity, getLatLon(), getAdditionalCardParams(), imageCardListener)); + } + } else { + checkTokenAndShowScreen(); + } + } + + private void showToastMessage(final String str) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + Toast.makeText(mapActivity.getBaseContext(), str, Toast.LENGTH_LONG).show(); + } + }); + } + + //This method runs on non main thread + private void checkTokenAndShowScreen() { + final String baseUrl = OPRWebviewActivity.getBaseUrl(app); + final String name = OPRWebviewActivity.getUsernameFromCookie(app); + final String privateKey = OPRWebviewActivity.getPrivateKeyFromCookie(app); + if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) { + String str = app.getString(R.string.cannot_upload_image); + showToastMessage(str); + } else { + app.runInUIThread(new Runnable() { + @Override + public void run() { + OprStartFragment.showInstance(mapActivity.getSupportFragmentManager()); + } + }); + } + } + + private byte[] compressImage(InputStream image) { + BufferedInputStream bufferedInputStream = new BufferedInputStream(image); + Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + bmp.compress(Bitmap.CompressFormat.PNG, 70, os); + return os.toByteArray(); + } + private void startLoadingImages() { if (onlinePhotoCardsRow == null) { return; } + startLoadingImagesTask(); + } + + private void startLoadingImagesTask() { onlinePhotoCards = new ArrayList<>(); onlinePhotoCardsRow.setProgressCard(); - execute(new GetImageCardsTask(mapActivity, getLatLon(), getAdditionalCardParams(), - new GetImageCardsListener() { - @Override - public void onPostProcess(List cardList) { - processOnlinePhotosCards(cardList); - } - - @Override - public void onFinish(List cardList) { - if (!isHidden()) { - List cards = new ArrayList<>(); - cards.addAll(cardList); - if (cardList.size() == 0) { - cards.add(new NoImagesCard(mapActivity)); - } - if (onlinePhotoCardsRow != null) { - onlinePhotoCardsRow.setCards(cards); - } - onlinePhotoCards = cards; - } - } - })); + execute(new GetImageCardsTask(mapActivity, getLatLon(), getAdditionalCardParams(), imageCardListener)); } protected Map getAdditionalCardParams() { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java index f0d33b68dd..12b1b0d497 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java @@ -32,11 +32,11 @@ import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.FontCache; +import net.osmand.plus.helpers.enums.MetricsConstants; import net.osmand.plus.mapcontextmenu.CollapsableView; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.osmedit.OsmEditingPlugin; import net.osmand.plus.poi.PoiUIFilter; -import net.osmand.plus.helpers.enums.MetricsConstants; import net.osmand.plus.views.layers.POIMapLayer; import net.osmand.plus.widgets.TextViewEx; import net.osmand.plus.widgets.tools.ClickableSpanTouchListener; @@ -48,7 +48,9 @@ import net.osmand.util.OpeningHoursParser; import org.apache.commons.logging.Log; +import java.io.UnsupportedEncodingException; import java.math.RoundingMode; +import java.net.URLDecoder; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.ArrayList; @@ -344,12 +346,11 @@ public class AmenityMenuBuilder extends MenuBuilder { boolean osmEditingEnabled = OsmandPlugin.getEnabledPlugin(OsmEditingPlugin.class) != null; - for (Map.Entry e : amenity.getAdditionalInfo().entrySet()) { + for (String key : amenity.getAdditionalInfoKeys()) { int iconId = 0; Drawable icon = null; int textColor = 0; - String key = e.getKey(); - String vl = e.getValue(); + String vl = amenity.getAdditionalInfo(key); if (key.equals("image") || key.equals("mapillary") @@ -460,7 +461,7 @@ public class AmenityMenuBuilder extends MenuBuilder { isCuisine = true; iconId = R.drawable.ic_action_cuisine; StringBuilder sb = new StringBuilder(); - for (String c : e.getValue().split(";")) { + for (String c : vl.split(";")) { if (sb.length() > 0) { sb.append(", "); sb.append(poiTypes.getPoiTranslation("cuisine_" + c).toLowerCase()); @@ -502,7 +503,6 @@ public class AmenityMenuBuilder extends MenuBuilder { isText = true; isDescription = iconId == R.drawable.ic_action_note_dark; textPrefix = pType.getTranslation(); - vl = amenity.unzipContent(e.getValue()); if (needIntFormatting) { vl = getFormattedInt(vl); } @@ -519,8 +519,7 @@ public class AmenityMenuBuilder extends MenuBuilder { } else if (poiType != null) { collectedPoiTypes.add(poiType); } else { - textPrefix = Algorithms.capitalizeFirstLetterAndLowercase(e.getKey()); - vl = amenity.unzipContent(e.getValue()); + textPrefix = Algorithms.capitalizeFirstLetterAndLowercase(key); } } @@ -782,26 +781,34 @@ public class AmenityMenuBuilder extends MenuBuilder { @Override protected Map getAdditionalCardParams() { Map params = new HashMap<>(); - Map additionalInfo = amenity.getAdditionalInfo(); - String imageValue = additionalInfo.get("image"); - String mapillaryValue = additionalInfo.get("mapillary"); - String wikidataValue = additionalInfo.get(Amenity.WIKIDATA); - String wikimediaValue = additionalInfo.get(Amenity.WIKIMEDIA_COMMONS); + String imageValue = amenity.getAdditionalInfo("image"); + String mapillaryValue = amenity.getAdditionalInfo("mapillary"); + String wikidataValue = amenity.getAdditionalInfo(Amenity.WIKIDATA); + String wikimediaValue = amenity.getAdditionalInfo(Amenity.WIKIMEDIA_COMMONS); if (!Algorithms.isEmpty(imageValue)) { - params.put("osm_image", imageValue); + params.put("osm_image", getDecodedAdditionalInfo(imageValue)); } if (!Algorithms.isEmpty(mapillaryValue)) { - params.put("osm_mapillary_key", mapillaryValue); + params.put("osm_mapillary_key", getDecodedAdditionalInfo(mapillaryValue)); } if (!Algorithms.isEmpty(wikidataValue)) { - params.put(Amenity.WIKIDATA, wikidataValue); + params.put(Amenity.WIKIDATA, getDecodedAdditionalInfo(wikidataValue)); } if (!Algorithms.isEmpty(wikimediaValue)) { - params.put(Amenity.WIKIMEDIA_COMMONS, wikimediaValue); + params.put(Amenity.WIKIMEDIA_COMMONS, getDecodedAdditionalInfo(wikimediaValue)); } return params; } + private String getDecodedAdditionalInfo(String additionalInfo) { + try { + return URLDecoder.decode(additionalInfo, "UTF-8"); + } catch (UnsupportedEncodingException e) { + LOG.error(e); + } + return additionalInfo; + } + private CollapsableView getPoiTypeCollapsableView(final Context context, boolean collapsed, @NonNull final List categoryTypes, final boolean poiAdditional, AmenityInfoRow textRow) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/IPFSImageCard.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/IPFSImageCard.java index 0d58add034..63f02d10fe 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/IPFSImageCard.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/IPFSImageCard.java @@ -1,8 +1,8 @@ package net.osmand.plus.mapcontextmenu.builders.cards; + import android.view.View; import androidx.core.content.ContextCompat; -import net.osmand.AndroidNetworkUtils; import net.osmand.PlatformUtil; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; @@ -12,7 +12,6 @@ import org.json.JSONException; import org.json.JSONObject; public class IPFSImageCard extends ImageCard { - private static final String BASE_URL = "https://test.openplacereviews.org/api/ipfs/image-ipfs?cid="; private static final Log LOG = PlatformUtil.getLog(IPFSImageCard.class); public IPFSImageCard(MapActivity mapActivity, JSONObject imageObject) { @@ -23,6 +22,7 @@ public class IPFSImageCard extends ImageCard { } catch (JSONException e) { LOG.error(e); } + String BASE_URL = mapActivity.getString(R.string.opr_base_url) + "api/ipfs/image-ipfs?cid="; url = BASE_URL + cid; imageHiresUrl = BASE_URL + cid; imageUrl = BASE_URL + cid; 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 26c81f03a7..49c23e9501 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java @@ -28,6 +28,7 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapillary.MapillaryContributeCard; import net.osmand.plus.mapillary.MapillaryImageCard; +import net.osmand.plus.openplacereviews.OPRWebviewActivity; import net.osmand.plus.wikimedia.WikiImageHelper; import net.osmand.util.Algorithms; @@ -42,6 +43,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; @@ -408,6 +410,28 @@ public abstract class ImageCard extends AbstractCard { } } + private static String[] getIdFromResponse(String response) { + try { + JSONArray obj = new JSONObject(response).getJSONArray("objects"); + JSONArray images = (JSONArray) ((JSONObject) obj.get(0)).get("id"); + return toStringArray(images); + } catch (JSONException e) { + e.printStackTrace(); + } + return new String[0]; + } + + private static String[] toStringArray(JSONArray array) { + if (array == null) + return null; + + String[] arr = new String[array.length()]; + for (int i = 0; i < arr.length; i++) { + arr[i] = array.optString(i); + } + return arr; + } + public static class GetImageCardsTask extends AsyncTask> { private MapActivity mapActivity; @@ -421,11 +445,13 @@ public abstract class ImageCard extends AbstractCard { public interface GetImageCardsListener { void onPostProcess(List cardList); + void onPlaceIdAcquired(String[] placeId); + void onFinish(List cardList); } public GetImageCardsTask(@NonNull MapActivity mapActivity, LatLon latLon, - @Nullable Map params, GetImageCardsListener listener) { + @Nullable Map params, GetImageCardsListener listener) { this.mapActivity = mapActivity; this.app = mapActivity.getMyApplication(); this.latLon = latLon; @@ -441,7 +467,15 @@ public abstract class ImageCard extends AbstractCard { if (o instanceof Amenity) { Amenity am = (Amenity) o; long amenityId = am.getId() >> 1; - getPicturesForPlace(result, amenityId); + String baseUrl = OPRWebviewActivity.getBaseUrl(app); + String url = baseUrl + "api/objects-by-index?type=opr.place&index=osmid&key=" + amenityId; + String response = AndroidNetworkUtils.sendRequest(app, url, Collections.emptyMap(), + "Requesting location images...", false, false); + if (response != null) { + getPicturesForPlace(result, response); + String[] id = getIdFromResponse(response); + listener.onPlaceIdAcquired(id); + } } try { final Map pms = new LinkedHashMap<>(); @@ -503,26 +537,27 @@ public abstract class ImageCard extends AbstractCard { return result; } - private void getPicturesForPlace(List result, long l) { - String url = "https://test.openplacereviews.org/api/objects-by-index?type=opr.place&index=osmid&limit=1&key=" + l; - String response = AndroidNetworkUtils.sendRequest(app, url, Collections.emptyMap(), - "Requesting location images...", false, false); + private void getPicturesForPlace(List result, String response) { try { if (!Algorithms.isEmpty(response)) { JSONArray obj = new JSONObject(response).getJSONArray("objects"); - JSONArray images = ((JSONObject) ((JSONObject) obj.get(0)).get("images")).getJSONArray("outdoor"); - if (images.length() > 0) { - for (int i = 0; i < images.length(); i++) { - try { - JSONObject imageObject = (JSONObject) images.get(i); - if (imageObject != JSONObject.NULL) { - ImageCard imageCard = ImageCard.createCardOpr(mapActivity, imageObject); - if (imageCard != null) { - result.add(imageCard); + JSONObject imagesWrapper = ((JSONObject) ((JSONObject) obj.get(0)).get("images")); + Iterator it = imagesWrapper.keys(); + while (it.hasNext()) { + JSONArray images = imagesWrapper.getJSONArray(it.next()); + if (images.length() > 0) { + for (int i = 0; i < images.length(); i++) { + try { + JSONObject imageObject = (JSONObject) images.get(i); + if (imageObject != JSONObject.NULL) { + ImageCard imageCard = ImageCard.createCardOpr(mapActivity, imageObject); + if (imageCard != null) { + result.add(imageCard); + } } + } catch (JSONException e) { + LOG.error(e); } - } catch (JSONException e) { - LOG.error(e); } } } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/AmenityMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/AmenityMenuController.java index aa65a39e90..11564a1b73 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/AmenityMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/AmenityMenuController.java @@ -12,13 +12,13 @@ import net.osmand.data.TransportStop; import net.osmand.osm.PoiCategory; import net.osmand.osm.PoiFilter; import net.osmand.osm.PoiType; -import net.osmand.plus.mapmarkers.MapMarker; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.MenuController; import net.osmand.plus.mapcontextmenu.builders.AmenityMenuBuilder; +import net.osmand.plus.mapmarkers.MapMarker; import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.transport.TransportStopRoute; import net.osmand.plus.wikipedia.WikipediaDialogFragment; @@ -26,7 +26,6 @@ import net.osmand.util.Algorithms; import net.osmand.util.OpeningHoursParser; import java.util.List; -import java.util.Map; public class AmenityMenuController extends MenuController { @@ -160,12 +159,9 @@ public class AmenityMenuController extends MenuController { String preferredLang = OsmandPlugin.onGetMapObjectPreferredLang(amenity, getPreferredMapAppLang(), getPreferredMapLang()); String name = amenity.getName(preferredLang, isTransliterateNames()); - Map additionalInfo = amenity.getAdditionalInfo(); - if (additionalInfo != null) { - String ref = additionalInfo.get("ref"); - if (!TextUtils.isEmpty(ref) && !ref.equals(name)) { - return name + " (" + ref + ")"; - } + String ref = amenity.getAdditionalInfo("ref"); + if (!TextUtils.isEmpty(ref) && !ref.equals(name)) { + return name + " (" + ref + ")"; } if (Algorithms.isEmpty(name) && amenity.getSubType().equalsIgnoreCase("atm")) { String operator = amenity.getAdditionalInfo("operator"); @@ -247,12 +243,9 @@ public class AmenityMenuController extends MenuController { @Override public Drawable getRightIcon() { - Map addTypes = amenity.getAdditionalInfo(); - if (addTypes != null) { - String region = addTypes.get("subway_region"); - if (region != null) { - return RenderingIcons.getBigIcon(getMapActivity(), "subway_" + region); - } + String region = amenity.getAdditionalInfo("subway_region"); + if (region != null) { + return RenderingIcons.getBigIcon(getMapActivity(), "subway_" + region); } return null; } diff --git a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryFiltersFragment.java b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryFiltersFragment.java index 60abf651ba..6b03cd3a6a 100644 --- a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryFiltersFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryFiltersFragment.java @@ -123,7 +123,7 @@ public class MapillaryFiltersFragment extends BaseOsmAndFragment { final DelayAutoCompleteTextView textView = (DelayAutoCompleteTextView) view.findViewById(R.id.auto_complete_text_view); textView.setAdapter(new MapillaryAutoCompleteAdapter(getContext(), R.layout.auto_complete_suggestion, getMyApplication())); String selectedUsername = settings.MAPILLARY_FILTER_USERNAME.get(); - if (!selectedUsername.equals("") && settings.USE_MAPILLARY_FILTER.get()) { + if (!selectedUsername.isEmpty() && settings.USE_MAPILLARY_FILTER.get()) { textView.setText(selectedUsername); textView.setSelection(selectedUsername.length()); } @@ -261,16 +261,16 @@ public class MapillaryFiltersFragment extends BaseOsmAndFragment { String dateFrom = dateFromEt.getText().toString(); String dateTo = dateToEt.getText().toString(); - if (!settings.MAPILLARY_FILTER_USERNAME.get().equals("") || !dateFrom.equals("") || !dateTo.equals("") || settings.MAPILLARY_FILTER_PANO.get()) { + if (!settings.MAPILLARY_FILTER_USERNAME.get().isEmpty() || !dateFrom.isEmpty() || !dateTo.isEmpty() || settings.MAPILLARY_FILTER_PANO.get()) { settings.USE_MAPILLARY_FILTER.set(true); } - if (dateFrom.equals("")) { + if (dateFrom.isEmpty()) { settings.MAPILLARY_FILTER_FROM_DATE.set(0L); } - if (dateTo.equals("")) { + if (dateTo.isEmpty()) { settings.MAPILLARY_FILTER_TO_DATE.set(0L); } - if (!username.equals("") && settings.MAPILLARY_FILTER_USERNAME.get().equals("")) { + if (!username.isEmpty() && settings.MAPILLARY_FILTER_USERNAME.get().isEmpty()) { view.findViewById(R.id.warning_linear_layout).setVisibility(View.VISIBLE); } else { mapActivity.getDashboard().hideDashboard(); diff --git a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryVectorLayer.java b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryVectorLayer.java index 512281a079..51c12f07aa 100644 --- a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryVectorLayer.java +++ b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryVectorLayer.java @@ -205,7 +205,7 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont long to = settings.MAPILLARY_FILTER_TO_DATE.get(); boolean pano = settings.MAPILLARY_FILTER_PANO.get(); - if (!userKey.equals("")) { + if (!userKey.isEmpty()) { String key = (String) userData.get("userkey"); if (!userKey.equals(key)) { return true; diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/DirectionIndicationDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/DirectionIndicationDialogFragment.java index d624ec7947..27ad98ece4 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/DirectionIndicationDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/DirectionIndicationDialogFragment.java @@ -277,7 +277,7 @@ public class DirectionIndicationDialogFragment extends BaseOsmAndDialogFragment } } ((ImageView) mainView.findViewById(R.id.action_bar_image)) - .setImageDrawable(new LayerDrawable(imgList.toArray(new Drawable[imgList.size()]))); + .setImageDrawable(new LayerDrawable(imgList.toArray(new Drawable[0]))); } else { mainView.findViewById(R.id.action_bar_image_container).setVisibility(View.GONE); } diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHelper.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHelper.java index d14ec40f4c..74797620f9 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHelper.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHelper.java @@ -1084,6 +1084,7 @@ public class MapMarkersHelper { String creationDateStr = point.getExtensionsToRead().get(CREATION_DATE); marker.visitedDate = parseTime(visitedDateStr, format); marker.creationDate = parseTime(creationDateStr, format); + marker.history = history; marker.nextKey = history ? MapMarkersDbHelper.HISTORY_NEXT_VALUE : MapMarkersDbHelper.TAIL_NEXT_VALUE; mapMarkers.add(marker); diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/SelectWptCategoriesBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/SelectWptCategoriesBottomSheetDialogFragment.java index d676372223..08db4d40fc 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/SelectWptCategoriesBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/SelectWptCategoriesBottomSheetDialogFragment.java @@ -81,7 +81,8 @@ public class SelectWptCategoriesBottomSheetDialogFragment extends MenuBottomShee Map> pointsByCategories = gpxFile.getPointsByCategories(); - for (String category : pointsByCategories.keySet()) { + for (Map.Entry> entry : pointsByCategories.entrySet()) { + String category = entry.getKey(); final BottomSheetItemWithCompoundButton[] categoryItem = new BottomSheetItemWithCompoundButton[1]; categoryItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() .setChecked(!isUpdateMode || (categories != null && categories.contains(category))) @@ -96,9 +97,9 @@ public class SelectWptCategoriesBottomSheetDialogFragment extends MenuBottomShee } }) .setCompoundButtonColorId(activeColorResId) - .setDescription(String.valueOf(pointsByCategories.get(category).size())) + .setDescription(String.valueOf(entry.getValue().size())) .setIcon(getContentIcon(R.drawable.ic_action_folder)) - .setTitle(category.equals("") ? getString(R.string.shared_string_waypoints) : category) + .setTitle(category.isEmpty() ? getString(R.string.shared_string_waypoints) : category) .setLayoutId(R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp) .setTag(category) .setOnClickListener(new View.OnClickListener() { diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersActiveAdapter.java b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersActiveAdapter.java index c1e85387b3..2fa206d08f 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersActiveAdapter.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersActiveAdapter.java @@ -131,7 +131,7 @@ public class MapMarkersActiveAdapter extends RecyclerView.Adapter it = categories.iterator(); while (it.hasNext()) { String category = it.next(); - if (category.equals("")) { + if (category.isEmpty()) { category = app.getResources().getString(R.string.shared_string_waypoints); } sb.append(category); diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersHistoryAdapter.java b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersHistoryAdapter.java index 87d8e54303..ba407b23f9 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersHistoryAdapter.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersHistoryAdapter.java @@ -145,7 +145,7 @@ public class MapMarkersHistoryAdapter extends RecyclerView.Adapter it = categories.iterator(); while (it.hasNext()) { String category = it.next(); - if (!category.equals("")) { + if (!category.isEmpty()) { sb.append(category); if (it.hasNext()) { sb.append(", "); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/LoginBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/LoginBottomSheetFragment.java index 3276bb2aa8..94ef66beab 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/LoginBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/LoginBottomSheetFragment.java @@ -16,6 +16,7 @@ import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities.DialogButtonType; +import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.osmedit.oauth.OsmOAuthHelper; @@ -24,7 +25,7 @@ import net.osmand.plus.settings.bottomsheets.OsmLoginDataBottomSheet; import org.apache.commons.logging.Log; import static net.osmand.plus.osmedit.OsmEditingFragment.OSM_LOGIN_DATA; -import static net.osmand.plus.osmedit.oauth.OsmOAuthHelper.*; +import static net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener; public class LoginBottomSheetFragment extends MenuBottomSheetDialogFragment implements OsmAuthorizationListener { @@ -89,6 +90,10 @@ public class LoginBottomSheetFragment extends MenuBottomSheetDialogFragment impl protected void onThirdBottomButtonClick() { View view = getView(); if (view != null) { + Fragment fragment = getTargetFragment(); + if (!(getActivity() instanceof MapActivity) && fragment instanceof OsmAuthorizationListener) { + osmOAuthHelper.addListener((OsmAuthorizationListener) fragment); + } osmOAuthHelper.startOAuth((ViewGroup) view); } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index 16c8e2309c..3b70d79f11 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -722,7 +722,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { if (editingCtx.getPointsCount() > 0) { - if (editingCtx.isNewData() || isInEditMode()) { + if (editingCtx.isNewData()) { if (showDialog) { openSaveAsNewTrackMenu(mapActivity); } else { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/RouteBetweenPointsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/RouteBetweenPointsBottomSheetDialogFragment.java index 8feb1ecf5c..54bc3469be 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/RouteBetweenPointsBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/RouteBetweenPointsBottomSheetDialogFragment.java @@ -14,26 +14,31 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import net.osmand.AndroidUtils; +import net.osmand.GPXUtilities.WptPt; import net.osmand.PlatformUtil; +import net.osmand.plus.OsmAndFormatter; 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.base.BottomSheetBehaviourDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.util.MapUtils; import org.apache.commons.logging.Log; import java.util.ArrayList; import java.util.List; -import static net.osmand.plus.UiUtilities.CustomRadioButtonType.START; import static net.osmand.plus.UiUtilities.CustomRadioButtonType.END; +import static net.osmand.plus.UiUtilities.CustomRadioButtonType.START; import static net.osmand.plus.measurementtool.MeasurementEditingContext.DEFAULT_APP_MODE; import static net.osmand.plus.measurementtool.SelectFileBottomSheet.BOTTOM_SHEET_HEIGHT_DP; public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBehaviourDialogFragment { + private static final Log LOG = PlatformUtil.getLog(RouteBetweenPointsBottomSheetDialogFragment.class); public static final String TAG = RouteBetweenPointsBottomSheetDialogFragment.class.getSimpleName(); public static final int STRAIGHT_LINE_TAG = -1; @@ -60,101 +65,6 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBeha ALL, } - private String getButtonText(RouteBetweenPointsDialogMode dialogMode) { - switch (dialogType) { - case WHOLE_ROUTE_CALCULATION: - switch (dialogMode) { - case SINGLE: - return getString(R.string.next_segment); - case ALL: - return getString(R.string.whole_track); - } - break; - case NEXT_ROUTE_CALCULATION: - switch (dialogMode) { - case SINGLE: - return getString(R.string.next_segment); - case ALL: - return getString(R.string.all_next_segments); - } - break; - case PREV_ROUTE_CALCULATION: - switch (dialogMode) { - case SINGLE: - return getString(R.string.previous_segment); - case ALL: - return getString(R.string.all_previous_segments); - } - break; - } - return ""; - } - - private String getButtonDescr(RouteBetweenPointsDialogMode dialogMode) { - switch (dialogType) { - case WHOLE_ROUTE_CALCULATION: - switch (dialogMode) { - case SINGLE: - return getString(R.string.route_between_points_next_segment_button_desc); - case ALL: - return getString(R.string.route_between_points_whole_track_button_desc); - } - break; - case NEXT_ROUTE_CALCULATION: - switch (dialogMode) { - case SINGLE: - return getString(R.string.only_selected_segment_recalc); - case ALL: - return getString(R.string.all_next_segments_will_be_recalc); - } - break; - case PREV_ROUTE_CALCULATION: - switch (dialogMode) { - case SINGLE: - return getString(R.string.only_selected_segment_recalc); - case ALL: - return getString(R.string.all_previous_segments_will_be_recalc); - } - break; - } - return ""; - } - - private void addDelimiterView(LinearLayout container) { - View row = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.divider, container, false); - View divider = row.findViewById(R.id.divider); - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) divider.getLayoutParams(); - params.topMargin = row.getResources().getDimensionPixelSize(R.dimen.bottom_sheet_title_padding_bottom); - params.bottomMargin = row.getResources().getDimensionPixelSize(R.dimen.bottom_sheet_title_padding_bottom); - container.addView(row); - } - - public void setDefaultDialogMode(RouteBetweenPointsDialogMode defaultDialogMode) { - this.defaultDialogMode = defaultDialogMode; - updateModeButtons(); - } - - public void updateModeButtons() { - UiUtilities.updateCustomRadioButtons(getMyApplication(), customRadioButton, nightMode, - defaultDialogMode == RouteBetweenPointsDialogMode.SINGLE ? START : END); - btnDescription.setText(getButtonDescr(defaultDialogMode)); - } - - private void addProfileView(LinearLayout container, View.OnClickListener onClickListener, Object tag, - Drawable icon, CharSequence title, boolean check) { - View row = UiUtilities.getInflater(getContext(), nightMode) - .inflate(R.layout.bottom_sheet_item_with_radio_btn, container, false); - ((RadioButton) row.findViewById(R.id.compound_button)).setChecked(check); - ImageView imageView = row.findViewById(R.id.icon); - imageView.setImageDrawable(icon); - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) imageView.getLayoutParams(); - params.rightMargin = container.getContext().getResources().getDimensionPixelSize(R.dimen.bottom_sheet_icon_margin_large); - ((TextView) row.findViewById(R.id.title)).setText(title); - row.setOnClickListener(onClickListener); - row.setTag(tag); - container.addView(row); - } - @Override public void createMenuItems(Bundle savedInstanceState) { Bundle args = getArguments(); @@ -173,6 +83,7 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBeha .inflate(R.layout.fragment_route_between_points_bottom_sheet_dialog, null, false); customRadioButton = mainView.findViewById(R.id.custom_radio_buttons); + customRadioButton.setMinimumHeight(getResources().getDimensionPixelSize(R.dimen.route_info_control_buttons_height)); TextView singleModeButton = mainView.findViewById(R.id.left_button); singleModeButton.setText(getButtonText(RouteBetweenPointsDialogMode.SINGLE)); TextView allModeButton = mainView.findViewById(R.id.right_button); @@ -253,6 +164,137 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBeha super.onDestroyView(); } + private void addDelimiterView(LinearLayout container) { + View row = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.divider, container, false); + View divider = row.findViewById(R.id.divider); + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) divider.getLayoutParams(); + params.topMargin = row.getResources().getDimensionPixelSize(R.dimen.bottom_sheet_title_padding_bottom); + params.bottomMargin = row.getResources().getDimensionPixelSize(R.dimen.bottom_sheet_title_padding_bottom); + container.addView(row); + } + + public void setDefaultDialogMode(RouteBetweenPointsDialogMode defaultDialogMode) { + this.defaultDialogMode = defaultDialogMode; + updateModeButtons(); + } + + public void updateModeButtons() { + UiUtilities.updateCustomRadioButtons(getMyApplication(), customRadioButton, nightMode, + defaultDialogMode == RouteBetweenPointsDialogMode.SINGLE ? START : END); + btnDescription.setText(getButtonDescr(defaultDialogMode)); + } + + private void addProfileView(LinearLayout container, View.OnClickListener onClickListener, Object tag, + Drawable icon, CharSequence title, boolean check) { + View row = UiUtilities.getInflater(getContext(), nightMode) + .inflate(R.layout.bottom_sheet_item_with_radio_btn, container, false); + ((RadioButton) row.findViewById(R.id.compound_button)).setChecked(check); + ImageView imageView = row.findViewById(R.id.icon); + imageView.setImageDrawable(icon); + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) imageView.getLayoutParams(); + params.rightMargin = container.getContext().getResources().getDimensionPixelSize(R.dimen.bottom_sheet_icon_margin_large); + ((TextView) row.findViewById(R.id.title)).setText(title); + row.setOnClickListener(onClickListener); + row.setTag(tag); + container.addView(row); + } + + private String getButtonText(RouteBetweenPointsDialogMode dialogMode) { + switch (dialogType) { + case WHOLE_ROUTE_CALCULATION: + switch (dialogMode) { + case SINGLE: + return getString(R.string.next_segment); + case ALL: + return getString(R.string.whole_track); + } + break; + case NEXT_ROUTE_CALCULATION: + String nextDescr = getDescription(false, dialogMode); + switch (dialogMode) { + case SINGLE: + return getString(R.string.ltr_or_rtl_combine_via_space, getString(R.string.next_segment), nextDescr); + case ALL: + return getString(R.string.ltr_or_rtl_combine_via_space, getString(R.string.all_next_segments), nextDescr); + } + break; + case PREV_ROUTE_CALCULATION: + String prevDescr = getDescription(true, dialogMode); + switch (dialogMode) { + case SINGLE: + return getString(R.string.ltr_or_rtl_combine_via_space, getString(R.string.previous_segment), prevDescr); + case ALL: + return getString(R.string.ltr_or_rtl_combine_via_space, getString(R.string.all_previous_segments), prevDescr); + } + break; + } + return ""; + } + + private String getButtonDescr(RouteBetweenPointsDialogMode dialogMode) { + switch (dialogType) { + case WHOLE_ROUTE_CALCULATION: + switch (dialogMode) { + case SINGLE: + return getString(R.string.route_between_points_next_segment_button_desc); + case ALL: + return getString(R.string.route_between_points_whole_track_button_desc); + } + break; + case NEXT_ROUTE_CALCULATION: + switch (dialogMode) { + case SINGLE: + return getString(R.string.only_selected_segment_recalc); + case ALL: + return getString(R.string.all_next_segments_will_be_recalc); + } + break; + case PREV_ROUTE_CALCULATION: + switch (dialogMode) { + case SINGLE: + return getString(R.string.only_selected_segment_recalc); + case ALL: + return getString(R.string.all_previous_segments_will_be_recalc); + } + break; + } + return ""; + } + + @NonNull + private String getDescription(boolean before, RouteBetweenPointsDialogMode dialogMode) { + MapActivity mapActivity = (MapActivity) getActivity(); + if (mapActivity == null) { + return ""; + } + MeasurementEditingContext editingCtx = mapActivity.getMapLayers().getMeasurementToolLayer().getEditingCtx(); + int pos = editingCtx.getSelectedPointPosition(); + List points = editingCtx.getPoints(); + + float dist = 0; + if (dialogMode == RouteBetweenPointsDialogMode.SINGLE) { + WptPt selectedPoint = points.get(pos); + WptPt second = points.get(before ? pos - 1 : pos + 1); + dist += MapUtils.getDistance(selectedPoint.lat, selectedPoint.lon, second.lat, second.lon); + } else { + int startIdx; + int endIdx; + if (before) { + startIdx = 1; + endIdx = pos; + } else { + startIdx = pos + 1; + endIdx = points.size() - 1; + } + for (int i = startIdx; i <= endIdx; i++) { + WptPt first = points.get(i - 1); + WptPt second = points.get(i); + dist += MapUtils.getDistance(first.lat, first.lon, second.lat, second.lon); + } + } + return OsmAndFormatter.getFormattedDistance(dist, mapActivity.getMyApplication()); + } + public static void showInstance(FragmentManager fm, Fragment targetFragment, RouteBetweenPointsDialogType dialogType, RouteBetweenPointsDialogMode defaultDialogMode, diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java index 29d48411fb..7cec05b764 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java @@ -2,6 +2,7 @@ package net.osmand.plus.measurementtool; import android.app.Activity; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.TextView; @@ -10,6 +11,7 @@ import androidx.annotation.NonNull; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; +import net.osmand.AndroidUtils; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; @@ -19,9 +21,10 @@ import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemButton; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; -import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; import net.osmand.util.Algorithms; +import java.io.File; + public class SavedTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { public static final String TAG = SavedTrackBottomSheetDialogFragment.class.getSimpleName(); @@ -68,27 +71,58 @@ public class SavedTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFr } }) .create()); + } - items.add(new DividerSpaceItem(getContext(), contextPaddingSmall)); + @Override + protected int getThirdBottomButtonTextId() { + return R.string.shared_string_share; + } - items.add(new BottomSheetItemButton.Builder() - .setButtonType(UiUtilities.DialogButtonType.SECONDARY) - .setTitle(getString(R.string.plan_route_create_new_route)) - .setLayoutId(R.layout.bottom_sheet_button) - .setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Activity activity = getActivity(); - if (activity instanceof MapActivity) { - MeasurementToolFragment.showInstance(((MapActivity) activity).getSupportFragmentManager(), - ((MapActivity) activity).getMapLocation()); - } - dismiss(); - } - }) - .create()); + @Override + protected void onThirdBottomButtonClick() { + final Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + final Uri fileUri = AndroidUtils.getUriForFile(getMyApplication(), new File(fileName)); + sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + sendIntent.setType("application/gpx+xml"); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + startActivity(sendIntent); + dismiss(); + } - items.add(new DividerSpaceItem(getContext(), contextPaddingSmall)); + @Override + protected UiUtilities.DialogButtonType getThirdBottomButtonType() { + return UiUtilities.DialogButtonType.SECONDARY; + } + + @Override + protected int getSecondDividerHeight() { + return getResources().getDimensionPixelSize(R.dimen.content_padding_small); + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.plan_route_create_new_route; + } + + @Override + protected UiUtilities.DialogButtonType getRightBottomButtonType() { + return UiUtilities.DialogButtonType.SECONDARY; + } + + @Override + protected void onRightBottomButtonClick() { + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + MeasurementToolFragment.showInstance(((MapActivity) activity).getSupportFragmentManager(), + ((MapActivity) activity).getMapLocation()); + } + dismiss(); + } + + @Override + protected int getFirstDividerHeight() { + return getResources().getDimensionPixelSize(R.dimen.context_menu_sub_info_height); } @Override diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java index 39ff57b20c..e6cccff706 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java @@ -159,7 +159,6 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo items.add(new OptionsDividerItem(getContext())); BaseBottomSheetItem changeRouteTypeBefore = new BottomSheetItemWithDescription.Builder() - .setDescription(getDescription(true)) .setIcon(getRouteTypeIcon(true)) .setTitle(getString(R.string.plan_route_change_route_type_before)) .setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp) @@ -178,7 +177,6 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo items.add(changeRouteTypeBefore); BaseBottomSheetItem changeRouteTypeAfter = new BottomSheetItemWithDescription.Builder() - .setDescription(getDescription(false)) .setIcon(getRouteTypeIcon(false)) .setTitle(getString(R.string.plan_route_change_route_type_after)) .setLayoutId(R.layout.bottom_sheet_item_with_descr_pad_32dp) diff --git a/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java b/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java index ec255b1bbc..e6c5f2ff1b 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java @@ -73,7 +73,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin { super(app); liveMonitoringHelper = new LiveMonitoringHelper(app); final List am = ApplicationMode.allPossibleValues(); - ApplicationMode.regWidgetVisibility("monitoring", am.toArray(new ApplicationMode[am.size()])); + ApplicationMode.regWidgetVisibility("monitoring", am.toArray(new ApplicationMode[0])); settings = app.getSettings(); pluginPreferences.add(settings.SAVE_TRACK_TO_GPX); pluginPreferences.add(settings.SAVE_TRACK_INTERVAL); diff --git a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java index 31cb5375fe..48c1dca711 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java @@ -80,11 +80,12 @@ import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.OsmandExpandableListFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; +import net.osmand.plus.helpers.enums.TracksSortByMode; import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.osmedit.OsmEditingPlugin; +import net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener; import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.helpers.enums.TracksSortByMode; import java.io.File; import java.text.DateFormat; @@ -112,7 +113,7 @@ import static net.osmand.util.Algorithms.objectEquals; import static net.osmand.util.Algorithms.removeAllFiles; public class AvailableGPXFragment extends OsmandExpandableListFragment implements - FavoritesFragmentStateHolder { + FavoritesFragmentStateHolder, OsmAuthorizationListener { public static final Pattern ILLEGAL_PATH_NAME_CHARACTERS = Pattern.compile("[?:\"*|<>]"); public static final int SEARCH_ID = -1; @@ -553,7 +554,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement public void doAction(int actionResId) { if (actionResId == R.string.shared_string_delete) { operationTask = new DeleteGpxTask(); - operationTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, selectedItems.toArray(new GpxInfo[selectedItems.size()])); + operationTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, selectedItems.toArray(new GpxInfo[0])); } else { operationTask = null; } @@ -922,6 +923,18 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement public void restoreState(Bundle bundle) { } + @Override + public void authorizationCompleted() { + Bundle bundle = new Bundle(); + bundle.putInt(TAB_ID, GPX_TAB); + + Intent intent = new Intent(app, app.getAppCustomization().getFavoritesActivity()); + intent.putExtra(MapActivity.INTENT_PARAMS, bundle); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); + + app.startActivity(intent); + } + public class LoadGpxTask extends AsyncTask> { private List result; @@ -996,7 +1009,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement List progress = new ArrayList<>(); loadGPXFolder(mapPath, result, loadTask, progress, ""); if (!progress.isEmpty()) { - loadTask.loadFile(progress.toArray(new GpxInfo[progress.size()])); + loadTask.loadFile(progress.toArray(new GpxInfo[0])); } } } @@ -1016,7 +1029,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement result.add(info); progress.add(info); if (progress.size() > 7) { - loadTask.loadFile(progress.toArray(new GpxInfo[progress.size()])); + loadTask.loadFile(progress.toArray(new GpxInfo[0])); progress.clear(); } } @@ -1462,7 +1475,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement list.add(GPXDataSetType.SLOPE); } if (list.size() > 0) { - gpxItem.chartTypes = list.toArray(new GPXDataSetType[list.size()]); + gpxItem.chartTypes = list.toArray(new GPXDataSetType[0]); } final OsmandSettings settings = app.getSettings(); settings.setMapLocationToShow(gpxItem.locationStart.lat, gpxItem.locationStart.lon, diff --git a/OsmAnd/src/net/osmand/plus/myplaces/FavoritesActivity.java b/OsmAnd/src/net/osmand/plus/myplaces/FavoritesActivity.java index c77cfbfc0d..43e1e73cc8 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/FavoritesActivity.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/FavoritesActivity.java @@ -60,6 +60,8 @@ public class FavoritesActivity extends TabActivity { private int tabSize; private ImportHelper importHelper; + private ViewPager viewPager; + private Bundle intentParams = null; @Override @@ -80,7 +82,7 @@ public class FavoritesActivity extends TabActivity { List mTabs = getTabItems(); setTabs(mTabs); - ViewPager mViewPager = (ViewPager) findViewById(R.id.pager); + viewPager = findViewById(R.id.pager); if (savedInstanceState == null) { Intent intent = getIntent(); if (intent != null && intent.hasExtra(MapActivity.INTENT_PARAMS)) { @@ -93,7 +95,7 @@ public class FavoritesActivity extends TabActivity { break; } } - mViewPager.setCurrentItem(pagerItem, false); + viewPager.setCurrentItem(pagerItem, false); } } } @@ -191,6 +193,17 @@ public class FavoritesActivity extends TabActivity { return mTabs; } + public Bundle storeCurrentState() { + int currentItem = viewPager.getCurrentItem(); + if (currentItem >= 0 && currentItem < fragList.size()) { + FavoritesFragmentStateHolder stateHolder = fragList.get(currentItem).get(); + if (stateHolder != null) { + return stateHolder.storeState(); + } + } + return null; + } + @Override public void onAttachFragment(Fragment fragment) { if (fragment instanceof FavoritesFragmentStateHolder) { diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java index e53b51cf39..08c68ac3e8 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java @@ -410,7 +410,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_SPEED); } } - tabTypes = tabTypeList.toArray(new GPXTabItemType[tabTypeList.size()]); + tabTypes = tabTypeList.toArray(new GPXTabItemType[0]); Context context = tabs.getContext(); titles = new String[tabTypes.length]; diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/AddPhotosBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/openplacereviews/AddPhotosBottomSheetDialogFragment.java new file mode 100644 index 0000000000..dae4fcad4b --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/AddPhotosBottomSheetDialogFragment.java @@ -0,0 +1,143 @@ +package net.osmand.plus.openplacereviews; + +import android.content.Context; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.Spanned; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +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.UiUtilities; +import net.osmand.plus.UiUtilities.DialogButtonType; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; +import net.osmand.plus.helpers.FontCache; +import net.osmand.plus.mapillary.MapillaryPlugin; +import net.osmand.plus.widgets.style.CustomTypefaceSpan; + +import org.apache.commons.logging.Log; + +public class AddPhotosBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { + + public static final String TAG = AddPhotosBottomSheetDialogFragment.class.getSimpleName(); + private static final Log LOG = PlatformUtil.getLog(AddPhotosBottomSheetDialogFragment.class); + + public static final String OPEN_PLACE_REVIEWS = "OpenPlaceReviews"; + public static final String MAPILLARY = "Mapillary"; + public static final String WEB_WIKIMEDIA = "Web / Wikimedia"; + public static final String OPEN_STREET_MAP = "OpenStreetMap"; + + @Override + public void createMenuItems(Bundle savedInstanceState) { + + OsmandApplication app = getMyApplication(); + if (app == null) { + return; + } + View view = View.inflate(UiUtilities.getThemedContext(app, nightMode), + R.layout.opr_add_photo, null); + setDescriptionSpan(view); + items.add(new SimpleBottomSheetItem.Builder() + .setCustomView(view) + .create()); + items.add(new DividerSpaceItem(app, app.getResources().getDimensionPixelSize(R.dimen.text_margin_small))); + } + + private void setDescriptionSpan(View view) { + String desc = requireContext().getString(R.string.add_photos_descr); + BoldSpannableString ss = new BoldSpannableString(desc, view.getContext()); + ss.setBold(OPEN_PLACE_REVIEWS); + ss.setBold(MAPILLARY); + ss.setBold(WEB_WIKIMEDIA); + ss.setBold(OPEN_STREET_MAP); + view.findViewById(R.id.add_photos_descr).setText(ss); + } + + static class BoldSpannableString extends SpannableString { + Context ctx; + + public BoldSpannableString(CharSequence source, Context ctx) { + super(source); + this.ctx = ctx; + } + + public void setBold(String boldText) { + String source = toString(); + setSpan(new CustomTypefaceSpan(FontCache.getRobotoMedium(ctx)), + source.indexOf(boldText), source.indexOf(boldText) + boldText.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + } + } + + @Override + protected int getThirdBottomButtonTextId() { + return R.string.add_to_opr; + } + + @Override + protected DialogButtonType getThirdBottomButtonType() { + return DialogButtonType.SECONDARY; + } + + @Override + protected int getFirstDividerHeight() { + return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_button_divider_height); + } + + @Override + protected void onThirdBottomButtonClick() { + FragmentActivity activity = getActivity(); + if (activity != null) { + OprStartFragment.showInstance(activity.getSupportFragmentManager()); + } + dismiss(); + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.add_to_mapillary; + } + + @Override + protected DialogButtonType getRightBottomButtonType() { + return DialogButtonType.SECONDARY; + } + + @Override + protected void onRightBottomButtonClick() { + FragmentActivity activity = getActivity(); + if (activity != null) { + MapillaryPlugin.openMapillary(activity, null); + } + dismiss(); + } + + @Override + protected int getSecondDividerHeight() { + return getResources().getDimensionPixelSize(R.dimen.content_padding_small); + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_cancel; + } + + public static void showInstance(@NonNull FragmentManager fm) { + try { + if (!fm.isStateSaved()) { + AddPhotosBottomSheetDialogFragment fragment = new AddPhotosBottomSheetDialogFragment(); + 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/openplacereviews/OPRWebviewActivity.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OPRWebviewActivity.java index ebcf32e4ec..62e030ecca 100644 --- a/OsmAnd/src/net/osmand/plus/openplacereviews/OPRWebviewActivity.java +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OPRWebviewActivity.java @@ -1,9 +1,12 @@ package net.osmand.plus.openplacereviews; +import android.content.Context; import android.graphics.PorterDuff; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.view.View; import android.webkit.CookieManager; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -11,44 +14,85 @@ import android.widget.TextView; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import net.osmand.AndroidUtils; -import net.osmand.plus.BuildConfig; +import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.OsmandActionBarActivity; +import net.osmand.plus.settings.backend.OsmandSettings; + +import java.util.ArrayList; +import java.util.List; public class OPRWebviewActivity extends OsmandActionBarActivity { public static final String KEY_LOGIN = "LOGIN_KEY"; - private static final String url = BuildConfig.OPR_BASE_URL; - private static final String cookieUrl = BuildConfig.OPR_BASE_URL + "profile"; - private static final String loginUrl = BuildConfig.OPR_BASE_URL + "login"; - private static final String registerUrl = BuildConfig.OPR_BASE_URL + "signup"; - private static final String finishUrl = cookieUrl; - public static String KEY_TITLE = "TITLE_KEY"; + public static final String KEY_TITLE = "TITLE_KEY"; + private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)"; private WebView webView; private boolean isLogin = false; + public static String getBaseUrl(Context ctx) { + return ctx.getString(R.string.opr_base_url); + } + + public static String getCookieUrl(Context ctx) { + return getBaseUrl(ctx) + "profile"; + } + + public static String getLoginUrl(Context ctx) { + return getBaseUrl(ctx) + "login"; + } + + public static String getRegisterUrl(Context ctx) { + return getBaseUrl(ctx) + "signup"; + } + + public static List getFinishUrls(Context ctx) { + String googleOAuthFinishUrl = getBaseUrl(ctx) + "auth?code=4"; + String profileUrl = getCookieUrl(ctx); + List urls = new ArrayList<>(); + urls.add(googleOAuthFinishUrl); + urls.add(profileUrl); + return urls; + } + public void onCreate(Bundle savedInstanceState) { + OsmandApplication app = getMyApplication(); + OsmandSettings settings = app.getSettings(); + boolean nightMode = !settings.isLightContent(); + int themeId = nightMode ? R.style.OsmandDarkTheme_NoActionbar : R.style.OsmandLightTheme_NoActionbar_LightStatusBar; + setTheme(themeId); + getWindow().setStatusBarColor(ContextCompat.getColor(this, nightMode + ? R.color.list_background_color_dark : R.color.list_background_color_light)); super.onCreate(savedInstanceState); setContentView(R.layout.activity_opr_webview); - Bundle b = getIntent().getExtras(); - setSupportActionBar(this.findViewById(R.id.toolbar)); - if (b != null) { - String title = b.getString(KEY_TITLE, ""); - this.findViewById(R.id.toolbar_text).setText(title); + Bundle bundle = getIntent().getExtras(); + Toolbar toolbar = findViewById(R.id.toolbar); + if (bundle != null) { + TextView titleView = findViewById(R.id.toolbar_text); + String title = bundle.getString(KEY_TITLE, ""); + titleView.setText(title); } - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - final Drawable upArrow = getMyApplication().getUIUtilities().getIcon(AndroidUtils.getNavigationIconResId(this)); + toolbar.setBackgroundDrawable(new ColorDrawable(AndroidUtils.getColorFromAttr(this, R.attr.bg_color))); + final Drawable upArrow = app.getUIUtilities().getIcon(AndroidUtils.getNavigationIconResId(this)); upArrow.setColorFilter(ContextCompat.getColor(this, R.color.color_favorite_gray), PorterDuff.Mode.SRC_ATOP); - getSupportActionBar().setHomeAsUpIndicator(upArrow); - webView = (WebView) findViewById(R.id.printDialogWebview); + toolbar.setNavigationIcon(upArrow); + toolbar.setNavigationContentDescription(R.string.access_shared_string_navigate_up); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onBackPressed(); + } + }); + webView = findViewById(R.id.printDialogWebview); + webView.getSettings().setUserAgentString(USER_AGENT); webView.setWebViewClient(new CloseOnSuccessWebViewClient()); webView.getSettings().setJavaScriptEnabled(true); WebView.setWebContentsDebuggingEnabled(true); - if (b != null) { - isLogin = b.getBoolean(KEY_LOGIN); + if (bundle != null) { + isLogin = bundle.getBoolean(KEY_LOGIN); if (isLogin) { - webView.loadUrl(loginUrl); + webView.loadUrl(getLoginUrl(this)); } else { - webView.loadUrl(registerUrl); + webView.loadUrl(getRegisterUrl(this)); } } } @@ -59,18 +103,18 @@ public class OPRWebviewActivity extends OsmandActionBarActivity { return true; } - public static String getPrivateKeyFromCookie() { - return returnCookieByKey("opr-token"); + public static String getPrivateKeyFromCookie(Context ctx) { + return returnCookieByKey(ctx, "opr-token"); } - public static String getUsernameFromCookie() { - return returnCookieByKey("opr-nickname"); + public static String getUsernameFromCookie(Context ctx) { + return returnCookieByKey(ctx, "opr-nickname"); } - private static String returnCookieByKey(String key) { + private static String returnCookieByKey(Context ctx, String key) { String CookieValue = null; CookieManager cookieManager = CookieManager.getInstance(); - String cookies = cookieManager.getCookie(cookieUrl); + String cookies = cookieManager.getCookie(getCookieUrl(ctx)); if (cookies == null || cookies.isEmpty()) { return ""; } @@ -88,8 +132,10 @@ public class OPRWebviewActivity extends OsmandActionBarActivity { public class CloseOnSuccessWebViewClient extends WebViewClient { @Override public void onPageFinished(WebView view, String url) { - if (url.contains(finishUrl) && isLogin) { - finish(); + for (String furl : getFinishUrls(OPRWebviewActivity.this)) { + if (url.contains(furl) && isLogin) { + finish(); + } } super.onPageFinished(view, url); } diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java index eecd0c3f32..d91164ff18 100644 --- a/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java @@ -1,6 +1,8 @@ package net.osmand.plus.openplacereviews; import android.content.Intent; +import android.graphics.Typeface; +import android.os.Build; import android.os.Bundle; import android.text.SpannableString; import android.text.Spanned; @@ -13,21 +15,39 @@ import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import net.osmand.PlatformUtil; +import net.osmand.plus.BuildConfig; import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; import net.osmand.plus.base.BaseOsmAndFragment; import org.apache.commons.logging.Log; public class OprStartFragment extends BaseOsmAndFragment { - private static final String TAG = "fragment_oprstart"; + private static final String TAG = OprStartFragment.class.getSimpleName(); private static final Log LOG = PlatformUtil.getLog(OprStartFragment.class); private static final String openPlaceReviewsUrl = "OpenPlaceReviews.org"; + private boolean nightMode; @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_opr_login, container, false); - v.findViewById(R.id.register_opr_create_account).setOnClickListener(new View.OnClickListener() { + nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls(); + View v = UiUtilities.getInflater(requireMyActivity(), nightMode).inflate(R.layout.fragment_opr_login, container, + false); + View createAccount = v.findViewById(R.id.register_opr_create_account); + v.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + FragmentActivity activity = getActivity(); + if (activity != null) { + activity.getSupportFragmentManager().popBackStack(); + } + } + }); + UiUtilities.setupDialogButton(nightMode, createAccount, UiUtilities.DialogButtonType.PRIMARY, + R.string.register_opr_create_new_account); + createAccount.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent i = new Intent(requireContext(), OPRWebviewActivity.class); @@ -36,13 +56,10 @@ public class OprStartFragment extends BaseOsmAndFragment { startActivity(i); } }); - v.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - getActivity().getSupportFragmentManager().popBackStack(); - } - }); - v.findViewById(R.id.register_opr_have_account).setOnClickListener(new View.OnClickListener() { + View haveAccount = v.findViewById(R.id.register_opr_have_account); + UiUtilities.setupDialogButton(nightMode, haveAccount, UiUtilities.DialogButtonType.SECONDARY, + R.string.register_opr_have_account); + haveAccount.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent i = new Intent(requireContext(), OPRWebviewActivity.class); @@ -58,12 +75,20 @@ public class OprStartFragment extends BaseOsmAndFragment { private void setURLSpan(View v) { String desc = requireContext().getString(R.string.register_on_openplacereviews_desc); SpannableString ss = new SpannableString(desc); - ss.setSpan(new URLSpanNoUnderline("https://" + openPlaceReviewsUrl), desc.indexOf(openPlaceReviewsUrl), + ss.setSpan(new URLSpanNoUnderline(getActivity().getString(R.string.opr_base_url)), desc.indexOf(openPlaceReviewsUrl), desc.indexOf(openPlaceReviewsUrl) + openPlaceReviewsUrl.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); v.findViewById(R.id.start_opr_description).setText(ss); v.findViewById(R.id.start_opr_description).setMovementMethod(LinkMovementMethod.getInstance()); } + @Override + public int getStatusBarColorId() { + View view = getView(); + if (view != null && Build.VERSION.SDK_INT >= 23 && !nightMode) { + view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } + return nightMode ? R.color.list_background_color_dark : R.color.list_background_color_light; + } private class URLSpanNoUnderline extends URLSpan { public URLSpanNoUnderline(String url) { @@ -71,9 +96,10 @@ public class OprStartFragment extends BaseOsmAndFragment { } @Override - public void updateDrawState(TextPaint ds) { + public void updateDrawState(@NonNull TextPaint ds) { super.updateDrawState(ds); ds.setUnderlineText(false); + ds.setTypeface(Typeface.DEFAULT_BOLD); } } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/AddPOIAction.java b/OsmAnd/src/net/osmand/plus/osmedit/AddPOIAction.java index 1db6bd0542..a46ddb0ba1 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/AddPOIAction.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/AddPOIAction.java @@ -222,8 +222,8 @@ public class AddPOIAction extends QuickAction { } addPoiToStringSet(getPoiTypes(activity).getOtherMapCategory(), tagKeys, valueKeys); tagKeys.addAll(EditPoiDialogFragment.BASIC_TAGS); - mAdapter.setTagData(tagKeys.toArray(new String[tagKeys.size()])); - mAdapter.setValueData(valueKeys.toArray(new String[valueKeys.size()])); + mAdapter.setTagData(tagKeys.toArray(new String[0])); + mAdapter.setValueData(valueKeys.toArray(new String[0])); Button addTagButton = (Button) view.findViewById(R.id.addTagButton); addTagButton.setOnClickListener(new View.OnClickListener() { @Override diff --git a/OsmAnd/src/net/osmand/plus/osmedit/AdvancedEditPoiFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/AdvancedEditPoiFragment.java index b538ccd0c5..a99afa7a22 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/AdvancedEditPoiFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/AdvancedEditPoiFragment.java @@ -89,8 +89,8 @@ public class AdvancedEditPoiFragment extends BaseOsmAndFragment addPoiToStringSet(abstractPoiType, tagKeys, valueKeys); } addPoiToStringSet(mapPoiTypes.getOtherMapCategory(), tagKeys, valueKeys); - mAdapter.setTagData(tagKeys.toArray(new String[tagKeys.size()])); - mAdapter.setValueData(valueKeys.toArray(new String[valueKeys.size()])); + mAdapter.setTagData(tagKeys.toArray(new String[0])); + mAdapter.setValueData(valueKeys.toArray(new String[0])); Button addTagButton = (Button) view.findViewById(R.id.addTagButton); addTagButton.setOnClickListener(new View.OnClickListener() { @Override diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java index ecdc776c78..55b24b7ed4 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java @@ -427,8 +427,6 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { f.setArguments(args); f.show(getChildFragmentManager(), "exceedDialog"); } else if (TextUtils.isEmpty(poiTypeEditText.getText())) { - HashSet tagsCopy = new HashSet<>(); - tagsCopy.addAll(editPoiData.getTagValues().keySet()); if (Algorithms.isEmpty(editPoiData.getTag(OSMSettings.OSMTagKey.ADDR_HOUSE_NUMBER.getValue()))) { SaveExtraValidationDialogFragment f = new SaveExtraValidationDialogFragment(); Bundle args = new Bundle(); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapLocalUtil.java b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapLocalUtil.java index 26eda5f4e5..4d42026026 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapLocalUtil.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapLocalUtil.java @@ -21,7 +21,6 @@ import org.apache.commons.logging.Log; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Set; import static net.osmand.osm.edit.Entity.POI_TYPE_TAG; @@ -136,12 +135,12 @@ public class OpenstreetmapLocalUtil implements OpenstreetmapUtil { if (!Algorithms.isEmpty(amenity.getOpeningHours())) { entity.putTagNoLC(OSMTagKey.OPENING_HOURS.getValue(), amenity.getOpeningHours()); } - for (Map.Entry entry : amenity.getAdditionalInfo().entrySet()) { - AbstractPoiType abstractPoi = MapPoiTypes.getDefault().getAnyPoiAdditionalTypeByKey(entry.getKey()); - if (abstractPoi != null && abstractPoi instanceof PoiType) { + for (String key : amenity.getAdditionalInfoKeys()) { + AbstractPoiType abstractPoi = MapPoiTypes.getDefault().getAnyPoiAdditionalTypeByKey(key); + if (abstractPoi instanceof PoiType) { PoiType p = (PoiType) abstractPoi; if (!p.isNotEditableOsm() && !Algorithms.isEmpty(p.getEditOsmTag())) { - entity.putTagNoLC(p.getEditOsmTag(), entry.getValue()); + entity.putTagNoLC(p.getEditOsmTag(), amenity.getAdditionalInfo(key)); } } } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java index 8940093c19..98256d0635 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java @@ -66,33 +66,19 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { @Override public EntityInfo getEntityInfo(long id) { - if(entityInfoId != null && entityInfoId.getId().longValue() == id) { + if (entityInfoId != null && entityInfoId.getId().longValue() == id) { return entityInfo; } return null; } - private static String getSiteApi() { - final int deviceApiVersion = android.os.Build.VERSION.SDK_INT; - - String RETURN_API; - - if (deviceApiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) { - RETURN_API = "https://api.openstreetmap.org/"; - } else { - RETURN_API = "http://api.openstreetmap.org/"; - } - - // RETURN_API = "http://api06.dev.openstreetmap.org/"; - - return RETURN_API; + private String getSiteApi() { + return settings.getOsmUrl(); } - private final static String URL_TO_UPLOAD_GPX = getSiteApi() + "api/0.6/gpx/create"; - public String uploadGPXFile(String tagstring, String description, String visibility, File f) { OsmOAuthAuthorizationAdapter adapter = new OsmOAuthAuthorizationAdapter(ctx); - String url = URL_TO_UPLOAD_GPX; + String url = getSiteApi() + "api/0.6/gpx/create"; Map additionalData = new LinkedHashMap(); additionalData.put("description", description); additionalData.put("tags", tagstring); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsLayer.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsLayer.java index 78b356fd03..71f7f112ec 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsLayer.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsLayer.java @@ -248,15 +248,8 @@ public class OsmBugsLayer extends OsmandMapLayer implements IContextMenuProvider } protected List loadingBugs(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude) { - final int deviceApiVersion = android.os.Build.VERSION.SDK_INT; - String SITE_API; - - if (deviceApiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) { - SITE_API = "https://api.openstreetmap.org/"; - } else { - SITE_API = "http://api.openstreetmap.org/"; - } + String SITE_API = activity.getMyApplication().getSettings().getOsmUrl(); List bugs = new ArrayList<>(); StringBuilder b = new StringBuilder(); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java index a6e2dd5ca8..5d6c172738 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java @@ -1,9 +1,12 @@ package net.osmand.plus.osmedit; +import com.github.scribejava.core.model.Response; + import net.osmand.PlatformUtil; import net.osmand.osm.io.Base64; import net.osmand.osm.io.NetworkUtils; +import net.osmand.osm.oauth.OsmOAuthAuthorizationClient; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.Version; @@ -19,6 +22,8 @@ import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutionException; public class OsmBugsRemoteUtil implements OsmBugsUtil { @@ -26,26 +31,12 @@ public class OsmBugsRemoteUtil implements OsmBugsUtil { private static final String GET = "GET"; private static final String POST = "POST"; - static String getNotesApi() { - final int deviceApiVersion = android.os.Build.VERSION.SDK_INT; - String RETURN_API; - if (deviceApiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) { - RETURN_API = "https://api.openstreetmap.org/api/0.6/notes"; - } else { - RETURN_API = "http://api.openstreetmap.org/api/0.6/notes"; - } - return RETURN_API; + String getNotesApi() { + return settings.getOsmUrl() + "api/0.6/notes"; } - static String getUserDetailsApi() { - final int deviceApiVersion = android.os.Build.VERSION.SDK_INT; - String RETURN_API; - if (deviceApiVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) { - RETURN_API = "https://api.openstreetmap.org/api/0.6/user/details"; - } else { - RETURN_API = "http://api.openstreetmap.org/api/0.6/user/details"; - } - return RETURN_API; + String getUserDetailsApi() { + return settings.getOsmUrl() + "api/0.6/user/details"; } private OsmandApplication app; @@ -107,57 +98,82 @@ public class OsmBugsRemoteUtil implements OsmBugsUtil { return editingPOI(getUserDetailsApi(), GET, "validate_login", false); } - private OsmBugResult editingPOI(String url, String requestMethod, String userOperation, - boolean anonymous) { - OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(app); - OsmBugResult r = new OsmBugResult(); - try { - HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url); - log.info("Editing poi " + url); - connection.setConnectTimeout(15000); - connection.setRequestMethod(requestMethod); - connection.setRequestProperty("User-Agent", Version.getFullVersion(app)); //$NON-NLS-1$ - - if (!anonymous) { - if (client.isValidToken()) { - connection.addRequestProperty("Authorization", "OAuth " + client.getClient().getAccessToken().getToken()); - } else { - String token = settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(); //$NON-NLS-1$ - connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes("UTF-8"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } + private OsmBugResult editingPOI(String url, String requestMethod, String userOperation, boolean anonymous) { + OsmOAuthAuthorizationAdapter authorizationAdapter = new OsmOAuthAuthorizationAdapter(app); + OsmBugResult result = new OsmBugResult(); + if (authorizationAdapter.isValidToken() && !anonymous) { + try { + result = performOAuthRequest(url, requestMethod, userOperation, authorizationAdapter); + } catch (InterruptedException e) { + log.error(e); + result.warning = e.getMessage(); + } catch (ExecutionException e) { + log.error(e); + result.warning = e.getMessage(); + } catch (IOException e) { + log.error(e); + result.warning = e.getMessage(); } - - connection.setDoInput(true); - connection.connect(); - String msg = connection.getResponseMessage(); - boolean ok = connection.getResponseCode() == HttpURLConnection.HTTP_OK; - log.info(msg); //$NON-NLS-1$ - // populate return fields. - - StringBuilder responseBody; - if (connection.getResponseCode() == HttpURLConnection.HTTP_CONFLICT) { - responseBody = Algorithms.readFromInputStream(connection.getErrorStream()); - } else { - responseBody = Algorithms.readFromInputStream(connection.getInputStream()); + } else { + try { + result = performBasicRequest(url, requestMethod, anonymous); + } catch (FileNotFoundException | NullPointerException e) { + // that's tricky case why NPE is thrown to fix that problem httpClient could be used + String msg = app.getString(R.string.auth_failed); + log.error(msg, e); + result.warning = app.getString(R.string.auth_failed) + ""; + } catch (MalformedURLException e) { + log.error(userOperation + " " + app.getString(R.string.failed_op), e); + result.warning = e.getMessage() + ""; + } catch (IOException e) { + log.error(userOperation + " " + app.getString(R.string.failed_op), e); + result.warning = e.getMessage() + " link unavailable"; } - log.info("Response : " + responseBody); //$NON-NLS-1$ - connection.disconnect(); - if (!ok) { - r.warning = msg + "\n" + responseBody; - } - } catch (FileNotFoundException | NullPointerException e) { - // that's tricky case why NPE is thrown to fix that problem httpClient could be used - String msg = app.getString(R.string.auth_failed); - log.error(msg, e); - r.warning = app.getString(R.string.auth_failed) + ""; - } catch (MalformedURLException e) { - log.error(userOperation + " " + app.getString(R.string.failed_op), e); //$NON-NLS-1$ - r.warning = e.getMessage() + ""; - } catch (IOException e) { - log.error(userOperation + " " + app.getString(R.string.failed_op), e); //$NON-NLS-1$ - r.warning = e.getMessage() + " link unavailable"; } - return r; + return result; } -} + private OsmBugResult performBasicRequest(String url, String requestMethod, boolean anonymous) throws IOException { + OsmBugResult result = new OsmBugResult(); + HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url); + log.info("Editing poi " + url); + connection.setConnectTimeout(15000); + connection.setRequestMethod(requestMethod); + connection.setRequestProperty("User-Agent", Version.getFullVersion(app)); + if (!anonymous) { + String token = settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(); + connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes(StandardCharsets.UTF_8))); + } + connection.setDoInput(true); + connection.connect(); + String msg = connection.getResponseMessage(); + boolean ok = connection.getResponseCode() == HttpURLConnection.HTTP_OK; + log.info(msg); + // populate return fields. + + StringBuilder responseBody; + if (connection.getResponseCode() == HttpURLConnection.HTTP_CONFLICT) { + responseBody = Algorithms.readFromInputStream(connection.getErrorStream()); + } else { + responseBody = Algorithms.readFromInputStream(connection.getInputStream()); + } + log.info("Response : " + responseBody); + connection.disconnect(); + if (!ok) { + result.warning = msg + "\n" + responseBody; + } + return result; + } + + private OsmBugResult performOAuthRequest(String url, String requestMethod, String userOperation, + OsmOAuthAuthorizationAdapter authorizationAdapter) + throws InterruptedException, ExecutionException, IOException { + OsmBugResult result = new OsmBugResult(); + OsmOAuthAuthorizationClient client = authorizationAdapter.getClient(); + Response response = client.performRequest(url, requestMethod, userOperation); + if (response.getCode() != HttpURLConnection.HTTP_OK) { + result.warning = response.getMessage() + "\n" + response.getBody(); + } + return result; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingFragment.java index d6156bfcfb..81cebe393d 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingFragment.java @@ -9,18 +9,20 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; +import androidx.activity.OnBackPressedCallback; +import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; -import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.FontCache; import net.osmand.plus.measurementtool.LoginBottomSheetFragment; import net.osmand.plus.osmedit.ValidateOsmLoginDetailsTask.ValidateOsmLoginListener; -import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter; +import net.osmand.plus.osmedit.oauth.OsmOAuthHelper; import net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener; import net.osmand.plus.settings.backend.OsmAndAppCustomization; import net.osmand.plus.settings.fragments.BaseSettingsFragment; @@ -29,27 +31,34 @@ import net.osmand.plus.settings.preferences.SwitchPreferenceEx; import net.osmand.plus.widgets.style.CustomTypefaceSpan; import net.osmand.util.Algorithms; -import org.apache.commons.logging.Log; - import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID; import static net.osmand.plus.osmedit.OsmEditingPlugin.OSM_EDIT_TAB; public class OsmEditingFragment extends BaseSettingsFragment implements OnPreferenceChanged, ValidateOsmLoginListener, OsmAuthorizationListener { - private static final Log log = PlatformUtil.getLog(OsmEditingFragment.class); - private static final String OSM_LOGOUT = "osm_logout"; private static final String OPEN_OSM_EDITS = "open_osm_edits"; public static final String OSM_LOGIN_DATA = "osm_login_data"; private static final String OSM_EDITING_INFO = "osm_editing_info"; - private OsmOAuthAuthorizationAdapter authorizationAdapter; + private OsmOAuthHelper authHelper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - authorizationAdapter = app.getOsmOAuthHelper().getAuthorizationAdapter(); + authHelper = app.getOsmOAuthHelper(); + + FragmentActivity activity = requireMyActivity(); + activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { + public void handleOnBackPressed() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.launchPrevActivityIntent(); + } + dismiss(); + } + }); } @Override @@ -61,6 +70,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer setupLogoutPref(); setupOfflineEditingPref(); + setupUseDevUrlPref(); setupOsmEditsDescrPref(); setupOsmEditsPref(); } @@ -112,7 +122,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer } private boolean isValidToken() { - return authorizationAdapter.isValidToken(); + return authHelper.isValidToken(); } private boolean isLoginExists() { @@ -129,6 +139,17 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer offlineEditingPref.setIcon(icon); } + private void setupUseDevUrlPref() { + SwitchPreferenceEx useDevUrlPref = findPreference(settings.USE_DEV_URL.getId()); + if (OsmandPlugin.isDevelopment()) { + Drawable icon = getPersistentPrefIcon(R.drawable.ic_action_laptop); + useDevUrlPref.setDescription(getString(R.string.use_dev_url_descr)); + useDevUrlPref.setIcon(icon); + } else { + useDevUrlPref.setVisible(false); + } + } + private void setupOsmEditsDescrPref() { String menu = getString(R.string.shared_string_menu); String myPlaces = getString(R.string.shared_string_my_places); @@ -152,6 +173,17 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer createProfile.setIcon(getActiveIcon(R.drawable.ic_action_folder)); } + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + String prefId = preference.getKey(); + if (settings.USE_DEV_URL.getId().equals(prefId) && newValue instanceof Boolean) { + settings.USE_DEV_URL.set((Boolean) newValue); + osmLogout(); + return true; + } + return super.onPreferenceChange(preference, newValue); + } + @Override public boolean onPreferenceClick(Preference preference) { String prefId = preference.getKey(); @@ -172,29 +204,32 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer return true; } } else if (OSM_LOGOUT.equals(prefId)) { - if (isValidToken()) { - settings.USER_ACCESS_TOKEN.resetToDefault(); - settings.USER_ACCESS_TOKEN_SECRET.resetToDefault(); - - authorizationAdapter.resetToken(); - } else { - settings.USER_NAME.resetToDefault(); - settings.USER_PASSWORD.resetToDefault(); - } - app.showShortToastMessage(R.string.osm_edit_logout_success); - updateAllSettings(); + osmLogout(); return true; } return super.onPreferenceClick(preference); } + public void osmLogout() { + if (authHelper.isValidToken() || isLoginExists()) { + app.showShortToastMessage(R.string.osm_edit_logout_success); + } + authHelper.resetAuthorization(); + updateAllSettings(); + } + @Override public void onPreferenceChanged(String prefId) { + if (settings.USE_DEV_URL.getId().equals(prefId)) { + osmLogout(); + } updateAllSettings(); } @Override public void authorizationCompleted() { - updateAllSettings(); + if (getContext() != null) { + updateAllSettings(); + } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java index a2ca2f0a61..90da6cc65d 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java @@ -415,7 +415,7 @@ public class OsmEditingPlugin extends OsmandPlugin { public void onClick(DialogInterface dialog, int which) { List selectedItems = f.getSelectedItems(); sendGPXFiles(activity, f, - selectedItems.toArray(new GpxInfo[selectedItems.size()])); + selectedItems.toArray(new GpxInfo[0])); } }); return true; @@ -461,10 +461,10 @@ public class OsmEditingPlugin extends OsmandPlugin { String pwd = settings.USER_PASSWORD.get(); String authToken = settings.USER_ACCESS_TOKEN.get(); if ((Algorithms.isEmpty(name) || Algorithms.isEmpty(pwd)) && Algorithms.isEmpty(authToken)) { - LoginBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), fragment.getTargetFragment()); + LoginBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), fragment); return false; } else { - SendGpxBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), fragment.getTargetFragment(), info); + SendGpxBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), fragment, info); return true; } } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsFragment.java index 7aff0a604f..380eeb8850 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsFragment.java @@ -42,11 +42,6 @@ import net.osmand.osm.edit.Entity; import net.osmand.osm.edit.Node; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.measurementtool.LoginBottomSheetFragment; -import net.osmand.plus.osmedit.dialogs.SendOsmNoteBottomSheetFragment; -import net.osmand.plus.osmedit.dialogs.SendPoiBottomSheetFragment; -import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.activities.ActionBarProgressActivity; @@ -55,14 +50,20 @@ import net.osmand.plus.activities.OsmandActionBarActivity; import net.osmand.plus.base.OsmAndListFragment; import net.osmand.plus.dialogs.ProgressDialogFragment; import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.measurementtool.LoginBottomSheetFragment; import net.osmand.plus.myplaces.FavoritesActivity; import net.osmand.plus.myplaces.FavoritesFragmentStateHolder; import net.osmand.plus.osmedit.ExportOptionsBottomSheetDialogFragment.ExportOptionsFragmentListener; import net.osmand.plus.osmedit.FileTypeBottomSheetDialogFragment.FileTypeFragmentListener; +import net.osmand.plus.osmedit.OpenstreetmapLocalUtil.OnNodeCommittedListener; import net.osmand.plus.osmedit.OsmEditOptionsBottomSheetDialogFragment.OsmEditOptionsFragmentListener; import net.osmand.plus.osmedit.OsmPoint.Group; -import net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment; -import net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.PoiUploaderType; +import net.osmand.plus.osmedit.dialogs.SendOsmNoteBottomSheetFragment; +import net.osmand.plus.osmedit.dialogs.SendPoiBottomSheetFragment; +import net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.ProgressDialogPoiUploader; +import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter; +import net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.util.Algorithms; import org.xmlpull.v1.XmlSerializer; @@ -80,8 +81,8 @@ import java.util.Map; import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID; import static net.osmand.plus.osmedit.OsmEditingPlugin.OSM_EDIT_TAB; -public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialogFragment.ProgressDialogPoiUploader, OpenstreetmapLocalUtil.OnNodeCommittedListener, - FavoritesFragmentStateHolder { +public class OsmEditsFragment extends OsmAndListFragment implements ProgressDialogPoiUploader, + OnNodeCommittedListener, FavoritesFragmentStateHolder, OsmAuthorizationListener { public static final int EXPORT_TYPE_ALL = 0; public static final int EXPORT_TYPE_POI = 1; @@ -105,6 +106,7 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo private final static int MODE_DELETE = 100; private final static int MODE_UPLOAD = 101; + private OsmandApplication app; private OsmEditingPlugin plugin; private View footerView; @@ -145,6 +147,7 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + app = getMyApplication(); if (savedInstanceState != null) { exportType = savedInstanceState.getInt(EXPORT_TYPE_KEY); } @@ -293,7 +296,7 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - uploadItems(osmEditsSelected.toArray(new OsmPoint[osmEditsSelected.size()])); + uploadItems(osmEditsSelected.toArray(new OsmPoint[0])); mode.finish(); return true; } @@ -591,7 +594,7 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo public void onClick(int type) { List points = getPointsToExport(); new BackupOpenstreetmapPointAsyncTask(type, exportType).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, - points.toArray(new OsmPoint[points.size()])); + points.toArray(new OsmPoint[0])); } }; } @@ -638,16 +641,28 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo && !Algorithms.isEmpty(settings.USER_PASSWORD.get()); if (hasPoiGroup(points)) { if (isLogged) { - SendPoiBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), points); + SendPoiBottomSheetFragment.showInstance(getChildFragmentManager(), points); } else { LoginBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), this); } } else { - SendOsmNoteBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), points); + SendOsmNoteBottomSheetFragment.showInstance(getChildFragmentManager(), points); } } } + @Override + public void authorizationCompleted() { + Bundle bundle = new Bundle(); + bundle.putInt(TAB_ID, OSM_EDIT_TAB); + + Intent intent = new Intent(app, app.getAppCustomization().getFavoritesActivity()); + intent.putExtra(MapActivity.INTENT_PARAMS, bundle); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); + + app.startActivity(intent); + } + boolean hasPoiGroup(OsmPoint[] points) { boolean hasPoiGroup = false; for (OsmPoint p : points) { @@ -669,9 +684,9 @@ public class OsmEditsFragment extends OsmAndListFragment implements SendPoiDialo @Override public void uploadEnded(Map loadErrorsMap) { super.uploadEnded(loadErrorsMap); - for (OsmPoint osmPoint : loadErrorsMap.keySet()) { - if (loadErrorsMap.get(osmPoint) == null) { - osmEdits.remove(osmPoint); + for (Map.Entry entry : loadErrorsMap.entrySet()) { + if (entry.getValue() == null) { + osmEdits.remove(entry.getKey()); } } recreateAdapterData(); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsUploadListenerHelper.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsUploadListenerHelper.java index 1d09b522ab..cbc37e1ea2 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsUploadListenerHelper.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsUploadListenerHelper.java @@ -59,8 +59,8 @@ public class OsmEditsUploadListenerHelper implements OsmEditsUploadListener { } int uploaded = 0; int pointsNum = loadErrorsMap.keySet().size(); - for (OsmPoint point : loadErrorsMap.keySet()) { - if (loadErrorsMap.get(point) == null) { + for (String s : loadErrorsMap.values()) { + if (s == null) { uploaded++; } } @@ -200,13 +200,14 @@ public class OsmEditsUploadListenerHelper implements OsmEditsUploadListener { boolean[] hasErrors = new boolean[loadErrorsMap.keySet().size()]; ArrayList pointsWithErrors = new ArrayList<>(); int i = 0; - for (OsmPoint point : loadErrorsMap.keySet()) { + for (Map.Entry entry : loadErrorsMap.entrySet()) { + OsmPoint point = entry.getKey(); pointNames[i] = point.getGroup() == OsmPoint.Group.BUG ? ((OsmNotesPoint) point).getText() : ((OpenstreetmapPoint) point).getName(); pointNames[i] = TextUtils.isEmpty(pointNames[i]) ? "id:" + point.getId() : pointNames[i]; - hasErrors[i] = loadErrorsMap.get(point) != null; + hasErrors[i] = entry.getValue() != null; if (hasErrors[i]) { pointsWithErrors.add(point); } @@ -221,7 +222,7 @@ public class OsmEditsUploadListenerHelper implements OsmEditsUploadListener { new UploadingMultipleErrorDialogFragment(); Bundle bundle = new Bundle(); bundle.putSerializable(POINTS_WITH_ERRORS, - pointsWithErrors.toArray(new OsmPoint[pointsWithErrors.size()])); + pointsWithErrors.toArray(new OsmPoint[0])); bundle.putStringArray(POINT_NAMES, pointNames); bundle.putBooleanArray(HAS_ERROR, hasErrors); fragment.setArguments(bundle); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/BugBottomSheetDialog.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/BugBottomSheetDialog.java index a865d0962c..3793196ce0 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/BugBottomSheetDialog.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/BugBottomSheetDialog.java @@ -55,7 +55,7 @@ public class BugBottomSheetDialog extends MenuBottomSheetDialogFragment { items.add(new TitleItem(getString(titleTextId))); View osmNoteView = View.inflate(UiUtilities.getThemedContext(app, nightMode), - R.layout.track_name_edit_text, null); + R.layout.open_osm_note_text, null); TextInputLayout textBox = osmNoteView.findViewById(R.id.name_text_box); int highlightColorId = nightMode ? R.color.list_background_color_dark : R.color.activity_background_color_light; textBox.setBoxBackgroundColorResource(highlightColorId); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/PoiSubTypeDialogFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/PoiSubTypeDialogFragment.java index 53b9ce0677..4c75a384ae 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/PoiSubTypeDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/PoiSubTypeDialogFragment.java @@ -36,7 +36,7 @@ public class PoiSubTypeDialogFragment extends DialogFragment { } else { addCategory(a, strings); } - final String[] subCats = strings.toArray(new String[strings.size()]); + final String[] subCats = strings.toArray(new String[0]); builder.setItems(subCats, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/PoiTypeDialogFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/PoiTypeDialogFragment.java index cdcf88fb0a..2278d8e8bd 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/PoiTypeDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/PoiTypeDialogFragment.java @@ -31,7 +31,7 @@ public class PoiTypeDialogFragment extends DialogFragment { categories.add(category); } } - builder.setItems(vals.toArray(new String[vals.size()]), new Dialog.OnClickListener() { + builder.setItems(vals.toArray(new String[0]), new Dialog.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { PoiCategory aType = categories.get(which); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendGpxBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendGpxBottomSheetFragment.java index 324f1f9d13..ecf089c0b1 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendGpxBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendGpxBottomSheetFragment.java @@ -1,10 +1,16 @@ package net.osmand.plus.osmedit.dialogs; +import android.graphics.Rect; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; import android.text.Editable; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.LinearLayout; +import android.widget.ScrollView; import android.widget.TextView; import androidx.annotation.NonNull; @@ -21,21 +27,26 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities.DialogButtonType; +import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem; import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo; +import net.osmand.plus.myplaces.FavoritesActivity; import net.osmand.plus.osmedit.OsmEditingPlugin; import net.osmand.plus.osmedit.OsmEditingPlugin.UploadVisibility; import net.osmand.plus.osmedit.UploadGPXFilesTask; import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.settings.fragments.BaseSettingsFragment; import net.osmand.util.Algorithms; import java.util.ArrayList; import java.util.List; +import static net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType.OPEN_STREET_MAP_EDITING; + public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { public static final String TAG = SendGpxBottomSheetFragment.class.getSimpleName(); @@ -45,6 +56,7 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { private TextInputEditText tagsField; private TextInputEditText messageField; + private int contentHeightPrevious = 0; public void setGpxInfos(GpxInfo[] gpxInfos) { this.gpxInfos = gpxInfos; @@ -57,6 +69,7 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { LayoutInflater themedInflater = UiUtilities.getInflater(app, nightMode); View sendOsmPoiView = themedInflater.inflate(R.layout.send_gpx_fragment, null); + sendOsmPoiView.getViewTreeObserver().addOnGlobalLayoutListener(getOnGlobalLayoutListener()); tagsField = sendOsmPoiView.findViewById(R.id.tags_field); messageField = sendOsmPoiView.findViewById(R.id.message_field); @@ -95,9 +108,18 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { visibilityDescription.setText(selectedUploadVisibility.getDescriptionId()); horizontalSelectionAdapter.notifyDataSetChanged(); } - }); - + LinearLayout account = sendOsmPoiView.findViewById(R.id.account_container); + account.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity activity = getActivity(); + if (activity != null) { + showOpenStreetMapScreen(activity); + } + dismiss(); + } + }); RecyclerView iconCategoriesRecyclerView = sendOsmPoiView.findViewById(R.id.description_view); iconCategoriesRecyclerView.setAdapter(horizontalSelectionAdapter); iconCategoriesRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false)); @@ -109,6 +131,53 @@ public class SendGpxBottomSheetFragment extends MenuBottomSheetDialogFragment { items.add(titleItem); } + private ViewTreeObserver.OnGlobalLayoutListener getOnGlobalLayoutListener() { + return new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + Rect visibleDisplayFrame = new Rect(); + int buttonsHeight = getResources().getDimensionPixelSize(R.dimen.dialog_button_ex_max_width); + int shadowHeight = getResources().getDimensionPixelSize(R.dimen.bottom_sheet_top_shadow_height); + final ScrollView scrollView = getView().findViewById(R.id.scroll_view); + scrollView.getWindowVisibleDisplayFrame(visibleDisplayFrame); + int height = scrollView.getHeight(); + int contentHeight = visibleDisplayFrame.bottom - visibleDisplayFrame.top - buttonsHeight; + if (contentHeightPrevious != contentHeight || contentHeight < height) { + if (scrollView.getHeight() + shadowHeight > contentHeight) { + scrollView.getLayoutParams().height = contentHeight; + } else { + scrollView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; + } + scrollView.requestLayout(); + int delay = Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP ? 300 : 1000; + scrollView.postDelayed(new Runnable() { + public void run() { + scrollView.scrollTo(0, scrollView.getHeight()); + } + }, delay); + contentHeightPrevious = contentHeight; + } + } + }; + } + + protected static void showOpenStreetMapScreen(@NonNull FragmentActivity activity) { + if (activity instanceof MapActivity) { + BaseSettingsFragment.showInstance(activity, OPEN_STREET_MAP_EDITING); + } else { + Bundle prevIntentParams = null; + if (activity instanceof FavoritesActivity) { + prevIntentParams = ((FavoritesActivity) activity).storeCurrentState(); + } else if (activity.getIntent() != null) { + prevIntentParams = activity.getIntent().getExtras(); + } + Bundle params = new Bundle(); + params.putString(BaseSettingsFragment.OPEN_SETTINGS, OPEN_STREET_MAP_EDITING.name()); + + MapActivity.launchMapActivityMoveToTop(activity, prevIntentParams, null, params); + } + } + @Override protected DialogButtonType getRightBottomButtonType() { return DialogButtonType.PRIMARY; diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendOsmNoteBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendOsmNoteBottomSheetFragment.java index 407e8c0b5f..d26c1ac212 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendOsmNoteBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendOsmNoteBottomSheetFragment.java @@ -1,16 +1,20 @@ package net.osmand.plus.osmedit.dialogs; +import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.ContextThemeWrapper; import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; +import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.widget.SwitchCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import com.google.android.material.textfield.TextInputLayout; @@ -36,8 +40,11 @@ import org.apache.commons.logging.Log; import static net.osmand.plus.UiUtilities.setupDialogButton; import static net.osmand.plus.osmedit.OsmEditingFragment.OSM_LOGIN_DATA; -import static net.osmand.plus.osmedit.ValidateOsmLoginDetailsTask.*; -import static net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.*; +import static net.osmand.plus.osmedit.ValidateOsmLoginDetailsTask.ValidateOsmLoginListener; +import static net.osmand.plus.osmedit.dialogs.SendGpxBottomSheetFragment.showOpenStreetMapScreen; +import static net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.OPENSTREETMAP_POINT; +import static net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.ProgressDialogPoiUploader; +import static net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.SimpleProgressDialogPoiUploader; public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragment implements ValidateOsmLoginListener, OsmAuthorizationListener { @@ -71,8 +78,9 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen final View sendOsmNoteView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.send_osm_note_fragment, null); - TextView noteText = sendOsmNoteView.findViewById(R.id.note_text); + EditText noteText = sendOsmNoteView.findViewById(R.id.note_text); noteText.setText(((OsmNotesPoint) poi[0]).getText()); + noteText.setSelection(noteText.getText().length()); TextInputLayout noteHint = sendOsmNoteView.findViewById(R.id.note_hint); noteHint.setHint(AndroidUtils.addColon(app, R.string.osn_bug_name)); accountBlockView = sendOsmNoteView.findViewById(R.id.account_container); @@ -86,7 +94,10 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen signInButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - OsmandApplication app = requiredMyApplication(); + Fragment fragment = getParentFragment(); + if (fragment instanceof OsmAuthorizationListener) { + app.getOsmOAuthHelper().addListener((OsmAuthorizationListener) fragment); + } app.getOsmOAuthHelper().startOAuth((ViewGroup) v); } }); @@ -120,6 +131,17 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen uploadAnonymously.setPadding(paddingSmall, 0, paddingSmall, 0); } }); + LinearLayout account = accountBlockView.findViewById(R.id.account_container); + account.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity activity = getActivity(); + if (activity != null) { + showOpenStreetMapScreen(activity); + } + dismiss(); + } + }); final SimpleBottomSheetItem bottomSheetItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() .setCustomView(sendOsmNoteView) .create(); @@ -171,9 +193,16 @@ public class SendOsmNoteBottomSheetFragment extends MenuBottomSheetDialogFragmen @Override protected void onRightBottomButtonClick() { - ProgressDialogPoiUploader progressDialogPoiUploader; - progressDialogPoiUploader = new SimpleProgressDialogPoiUploader((MapActivity) getActivity()); - progressDialogPoiUploader.showProgressDialog(poi, false, uploadAnonymously.isChecked()); + ProgressDialogPoiUploader progressDialogPoiUploader = null; + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + progressDialogPoiUploader = new SimpleProgressDialogPoiUploader((MapActivity) activity); + } else if (getParentFragment() instanceof ProgressDialogPoiUploader) { + progressDialogPoiUploader = (ProgressDialogPoiUploader) getParentFragment(); + } + if (progressDialogPoiUploader != null) { + progressDialogPoiUploader.showProgressDialog(poi, false, uploadAnonymously.isChecked()); + } dismiss(); } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiBottomSheetFragment.java index 7755568e43..6bb227c2d3 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiBottomSheetFragment.java @@ -1,14 +1,17 @@ package net.osmand.plus.osmedit.dialogs; +import android.app.Activity; import android.os.Bundle; import android.view.ContextThemeWrapper; import android.view.View; import android.widget.CompoundButton; import android.widget.EditText; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.widget.SwitchCompat; +import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import net.osmand.PlatformUtil; @@ -30,7 +33,10 @@ import org.apache.commons.logging.Log; import java.util.HashMap; import java.util.Map; -import static net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.*; +import static net.osmand.plus.osmedit.dialogs.SendGpxBottomSheetFragment.showOpenStreetMapScreen; +import static net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.OPENSTREETMAP_POINT; +import static net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.ProgressDialogPoiUploader; +import static net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment.SimpleProgressDialogPoiUploader; public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment { @@ -60,6 +66,7 @@ public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment { messageEditText = sendOsmPoiView.findViewById(R.id.message_field); String defaultChangeSet = createDefaultChangeSet(app); messageEditText.setText(defaultChangeSet); + messageEditText.setSelection(messageEditText.getText().length()); final TextView accountName = sendOsmPoiView.findViewById(R.id.user_name); OsmandSettings settings = app.getSettings(); String userNameOAuth = settings.USER_DISPLAY_NAME.get(); @@ -82,6 +89,17 @@ public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment { closeChangeSet.setPadding(paddingSmall, 0, paddingSmall, 0); } }); + LinearLayout account = sendOsmPoiView.findViewById(R.id.account_container); + account.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity activity = getActivity(); + if (activity != null) { + showOpenStreetMapScreen(activity); + } + dismiss(); + } + }); final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() .setCustomView(sendOsmPoiView) .create(); @@ -109,19 +127,25 @@ public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment { @Override protected void onRightBottomButtonClick() { - final ProgressDialogPoiUploader progressDialogPoiUploader; - progressDialogPoiUploader = new SimpleProgressDialogPoiUploader((MapActivity) getActivity()); - - String comment = messageEditText.getText().toString(); - if (comment.length() > 0) { - for (OsmPoint osmPoint : poi) { - if (osmPoint.getGroup() == OsmPoint.Group.POI) { - ((OpenstreetmapPoint) osmPoint).setComment(comment); - break; + ProgressDialogPoiUploader progressDialogPoiUploader = null; + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + progressDialogPoiUploader = new SimpleProgressDialogPoiUploader((MapActivity) activity); + } else if (getParentFragment() instanceof ProgressDialogPoiUploader) { + progressDialogPoiUploader = (ProgressDialogPoiUploader) getParentFragment(); + } + if (progressDialogPoiUploader != null) { + String comment = messageEditText.getText().toString(); + if (comment.length() > 0) { + for (OsmPoint osmPoint : poi) { + if (osmPoint.getGroup() == OsmPoint.Group.POI) { + ((OpenstreetmapPoint) osmPoint).setComment(comment); + break; + } } } + progressDialogPoiUploader.showProgressDialog(poi, closeChangeSet.isChecked(), false); } - progressDialogPoiUploader.showProgressDialog(poi, closeChangeSet.isChecked(), false); dismiss(); } @@ -226,7 +250,7 @@ public class SendPoiBottomSheetFragment extends MenuBottomSheetDialogFragment { if (modifiedItemsOutOfLimit != 0) { comment = comment.concat("; ").concat(modifiedItemsOutOfLimit + " ") .concat(getString(R.string.items_modified)).concat("."); - } else if (!comment.equals("")) { + } else if (!comment.isEmpty()) { comment = comment.concat("."); } return comment; diff --git a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiDialogFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiDialogFragment.java index d402cdfe49..adfb8a2b60 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/dialogs/SendPoiDialogFragment.java @@ -84,7 +84,7 @@ public class SendPoiDialogFragment extends DialogFragment { messageLabel.setVisibility(hasPOI ? View.VISIBLE : View.GONE); messageEditText.setVisibility(hasPOI ? View.VISIBLE : View.GONE); closeChangeSetCheckBox.setVisibility(hasPOI ? View.VISIBLE : View.GONE); - closeChangeSetCheckBox.setChecked(hasPOI && !defaultChangeSet.equals("")); + closeChangeSetCheckBox.setChecked(hasPOI && !defaultChangeSet.isEmpty()); view.findViewById(R.id.osm_note_header).setVisibility(hasPOI ? View.GONE : View.VISIBLE); uploadAnonymously.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override @@ -233,7 +233,7 @@ public class SendPoiDialogFragment extends DialogFragment { } if (modifiedItemsOutOfLimit != 0) { comment = comment.concat("; ").concat(modifiedItemsOutOfLimit + " ").concat(getString(R.string.items_modified)).concat("."); - } else if (!comment.equals("")){ + } else if (!comment.isEmpty()){ comment = comment.concat("."); } return comment; diff --git a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java index 7c2562b580..5df7bfb765 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java @@ -1,10 +1,14 @@ package net.osmand.plus.osmedit.oauth; import android.net.TrafficStats; +import android.os.AsyncTask; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; +import androidx.annotation.NonNull; + +import com.github.scribejava.core.builder.api.DefaultApi10a; import com.github.scribejava.core.model.OAuth1AccessToken; import com.github.scribejava.core.model.OAuth1RequestToken; import com.github.scribejava.core.model.OAuthAsyncRequestCallback; @@ -13,9 +17,11 @@ import com.github.scribejava.core.model.Verb; import net.osmand.PlatformUtil; import net.osmand.osm.oauth.OsmOAuthAuthorizationClient; -import net.osmand.plus.BuildConfig; +import net.osmand.plus.OsmAndConstants; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import org.apache.commons.logging.Log; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -27,15 +33,27 @@ public class OsmOAuthAuthorizationAdapter { private static final int THREAD_ID = 10101; private static final String OSM_USER = "user"; private static final String DISPLAY_NAME = "display_name"; - private static final String OSM_USER_DETAILS_URL = "https://api.openstreetmap.org/api/0.6/user/details"; + public final static Log log = PlatformUtil.getLog(OsmOAuthAuthorizationAdapter.class); private OsmandApplication app; - private OsmOAuthAuthorizationClient client = - new OsmOAuthAuthorizationClient(BuildConfig.OSM_OAUTH_CONSUMER_KEY, BuildConfig.OSM_OAUTH_CONSUMER_SECRET); + private final OsmOAuthAuthorizationClient client; public OsmOAuthAuthorizationAdapter(OsmandApplication app) { TrafficStats.setThreadStatsTag(THREAD_ID); this.app = app; + DefaultApi10a api10a; + String key; + String secret; + if (app.getSettings().USE_DEV_URL.get()) { + api10a = new OsmOAuthAuthorizationClient.OsmDevApi(); + key = app.getString(R.string.osm_oauth_developer_key); + secret = app.getString(R.string.osm_oauth_developer_secret); + } else { + api10a = new OsmOAuthAuthorizationClient.OsmApi(); + key = app.getString(R.string.osm_oauth_consumer_key); + secret = app.getString(R.string.osm_oauth_consumer_secret); + } + client = new OsmOAuthAuthorizationClient(key, secret, api10a); restoreToken(); } @@ -61,9 +79,8 @@ public class OsmOAuthAuthorizationAdapter { } } - public void startOAuth(ViewGroup rootLayout) { - OAuth1RequestToken requestToken = client.startOAuth(); - loadWebView(rootLayout, client.getService().getAuthorizationUrl(requestToken)); + public void startOAuth(final ViewGroup rootLayout) { + new StartOAuthAsyncTask(rootLayout).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } private void saveToken() { @@ -93,30 +110,87 @@ public class OsmOAuthAuthorizationAdapter { return client.performRequestWithoutAuth(url, method, body); } - public void authorize(String oauthVerifier) { - client.authorize(oauthVerifier); - saveToken(); + public void authorize(String oauthVerifier, OsmOAuthHelper helper) { + new AuthorizeAsyncTask(helper).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, oauthVerifier); } - public String getUserName() throws InterruptedException, ExecutionException, IOException, XmlPullParserException { - Response response = getOsmUserDetails(); - return parseUserName(response); + private class StartOAuthAsyncTask extends AsyncTask { + + private final ViewGroup rootLayout; + + public StartOAuthAsyncTask(ViewGroup rootLayout) { + this.rootLayout = rootLayout; + } + + @Override + protected OAuth1RequestToken doInBackground(Void... params) { + return client.startOAuth(); + } + + @Override + protected void onPostExecute(@NonNull OAuth1RequestToken requestToken) { + loadWebView(rootLayout, client.getService().getAuthorizationUrl(requestToken)); + } } + private class AuthorizeAsyncTask extends AsyncTask { + + private final OsmOAuthHelper helper; + + public AuthorizeAsyncTask(OsmOAuthHelper helper) { + this.helper = helper; + } + + @Override + protected Void doInBackground(String... oauthVerifier) { + client.authorize(oauthVerifier[0]); + saveToken(); + updateUserName(); + return null; + } + + @Override + protected void onPostExecute(Void result) { + helper.notifyAndRemoveListeners(); + } + + public void updateUserName() { + String userName = ""; + try { + userName = getUserName(); + } catch (InterruptedException e) { + log.error(e); + } catch (ExecutionException e) { + log.error(e); + } catch (IOException e) { + log.error(e); + } catch (XmlPullParserException e) { + log.error(e); + } + app.getSettings().USER_DISPLAY_NAME.set(userName); + } + + public String getUserName() throws InterruptedException, ExecutionException, IOException, XmlPullParserException { + Response response = getOsmUserDetails(); + return parseUserName(response); + } + public Response getOsmUserDetails() throws InterruptedException, ExecutionException, IOException { - return performRequest(OSM_USER_DETAILS_URL, Verb.GET.name(), null); + String osmUserDetailsUrl = app.getSettings().getOsmUrl() + "api/0.6/user/details"; + return performRequest(osmUserDetailsUrl, Verb.GET.name(), null); } - public String parseUserName(Response response) throws XmlPullParserException, IOException { - String userName = null; - XmlPullParser parser = PlatformUtil.newXMLPullParser(); - parser.setInput(response.getStream(), "UTF-8"); - int tok; - while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (tok == XmlPullParser.START_TAG && OSM_USER.equals(parser.getName())) { - userName = parser.getAttributeValue("", DISPLAY_NAME); + public String parseUserName(Response response) throws XmlPullParserException, IOException { + String userName = null; + XmlPullParser parser = PlatformUtil.newXMLPullParser(); + parser.setInput(response.getStream(), "UTF-8"); + int tok; + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (tok == XmlPullParser.START_TAG && OSM_USER.equals(parser.getName())) { + userName = parser.getAttributeValue("", DISPLAY_NAME); + } } + return userName; } - return userName; } } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthHelper.java b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthHelper.java index d13bf624f2..acda0e0361 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthHelper.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthHelper.java @@ -4,55 +4,76 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; -import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.util.Algorithms; -import org.apache.commons.logging.Log; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.concurrent.ExecutionException; +import java.util.HashSet; +import java.util.Set; public class OsmOAuthHelper { - private static final Log log = PlatformUtil.getLog(OsmOAuthHelper.class); - private final OsmandApplication app; - - private final OsmOAuthAuthorizationAdapter authorizationAdapter; + private OsmOAuthAuthorizationAdapter authorizationAdapter; + private final Set listeners = new HashSet<>(); + private final OsmandSettings settings; public OsmOAuthHelper(@NonNull OsmandApplication app) { this.app = app; + settings = app.getSettings(); authorizationAdapter = new OsmOAuthAuthorizationAdapter(app); } - public void startOAuth(ViewGroup view) { - authorizationAdapter.startOAuth(view); + public void addListener(OsmAuthorizationListener listener) { + listeners.add(listener); } - public void authorize(String oauthVerifier) { - authorizationAdapter.authorize(oauthVerifier); - updateUserName(); + public OsmOAuthAuthorizationAdapter updateAdapter(){ + authorizationAdapter = new OsmOAuthAuthorizationAdapter(app); + return authorizationAdapter; + } + + public void removeListener(OsmAuthorizationListener listener) { + listeners.remove(listener); } public OsmOAuthAuthorizationAdapter getAuthorizationAdapter() { return authorizationAdapter; } - private void updateUserName() { - String userName = ""; - try { - userName = authorizationAdapter.getUserName(); - } catch (InterruptedException e) { - log.error(e); - } catch (ExecutionException e) { - log.error(e); - } catch (IOException e) { - log.error(e); - } catch (XmlPullParserException e) { - log.error(e); + public void startOAuth(@NonNull ViewGroup view) { + authorizationAdapter.startOAuth(view); + } + + public void authorize(@NonNull String oauthVerifier) { + authorizationAdapter.authorize(oauthVerifier, this); + } + + public void resetAuthorization() { + if (isValidToken()) { + settings.USER_ACCESS_TOKEN.resetToDefault(); + settings.USER_ACCESS_TOKEN_SECRET.resetToDefault(); + authorizationAdapter.resetToken(); + } else if (isLoginExists()) { + settings.USER_NAME.resetToDefault(); + settings.USER_PASSWORD.resetToDefault(); } - app.getSettings().USER_DISPLAY_NAME.set(userName); + updateAdapter(); + } + + private boolean isLoginExists() { + return !Algorithms.isEmpty(settings.USER_NAME.get()) && !Algorithms.isEmpty(settings.USER_PASSWORD.get()); + } + + public void notifyAndRemoveListeners() { + for (OsmAuthorizationListener listener : listeners) { + listener.authorizationCompleted(); + } + listeners.clear(); + } + + public boolean isValidToken() { + return authorizationAdapter.isValidToken(); } public interface OsmAuthorizationListener { diff --git a/OsmAnd/src/net/osmand/plus/osmedit/opr/OpenDBAPI.java b/OsmAnd/src/net/osmand/plus/osmedit/opr/OpenDBAPI.java new file mode 100644 index 0000000000..36d6e82b11 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/osmedit/opr/OpenDBAPI.java @@ -0,0 +1,151 @@ +package net.osmand.plus.osmedit.opr; + +import android.net.TrafficStats; +import android.os.Build; + +import com.google.gson.GsonBuilder; + +import net.osmand.PlatformUtil; +import net.osmand.osm.io.NetworkUtils; + +import org.apache.commons.logging.Log; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.openplacereviews.opendb.SecUtils; +import org.openplacereviews.opendb.ops.OpOperation; +import org.openplacereviews.opendb.util.JsonFormatter; +import org.openplacereviews.opendb.util.exception.FailedVerificationException; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.security.KeyPair; +import java.security.Security; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import static org.openplacereviews.opendb.SecUtils.ALGO_EC; +import static org.openplacereviews.opendb.SecUtils.JSON_MSG_TYPE; +import static org.openplacereviews.opendb.SecUtils.signMessageWithKeyBase64; + + +public class OpenDBAPI { + private static final Log log = PlatformUtil.getLog(SecUtils.class); + private static final String checkLoginEndpoint = "api/auth/user-check-loginkey?"; + private static final String LOGIN_SUCCESS_MESSAGE = "{\"result\":\"OK\"}"; + private static final int THREAD_ID = 11200; + + /* + * method for check if user is loggined in blockchain + * params + * - username: blockchain username in format "openplacereviews:test_1" + * - privatekey: "base64:PKCS#8:actualKey" + * Need to encode key + * Do not call on mainThread + */ + public boolean checkPrivateKeyValid(String baseUrl, String username, String privateKey) { + String url = null; + try { + url = baseUrl + checkLoginEndpoint + + "name=" + + username + + "&" + + "privateKey=" + + //need to encode the key + URLEncoder.encode(privateKey, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return false; + } + StringBuilder response = new StringBuilder(); + return (NetworkUtils.sendGetRequest(url,null,response) == null) && + response.toString().contains(LOGIN_SUCCESS_MESSAGE); + } + + public int uploadImage(String[] placeId, String baseUrl, String privateKey, String username, String image, StringBuilder sb) throws FailedVerificationException { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + Security.removeProvider("BC"); + Security.addProvider(new BouncyCastleProvider()); + } + KeyPair kp = SecUtils.getKeyPair(ALGO_EC, privateKey, null); + String signed = username + ":opr-web"; + + JsonFormatter formatter = new JsonFormatter(); + OPRImage oprImage = new GsonBuilder().create().fromJson(image, OPRImage.class); + OpOperation opOperation = new OpOperation(); + opOperation.setType("opr.place"); + List edits = new ArrayList<>(); + Map edit = new TreeMap<>(); + List imageResponseList = new ArrayList<>(); + Map imageMap = new TreeMap<>(); + imageMap.put("cid", oprImage.cid); + imageMap.put("hash", oprImage.hash); + imageMap.put("extension", oprImage.extension); + imageMap.put("type", oprImage.type); + imageResponseList.add(imageMap); + List ids = new ArrayList<>(Arrays.asList(placeId)); + Map change = new TreeMap<>(); + Map images = new TreeMap<>(); + images.put("append", imageMap); + change.put("version", "increment"); + change.put("images.review", images); + edit.put("id", ids); + edit.put("change", change); + edit.put("current", new Object()); + edits.add(edit); + opOperation.putObjectValue(OpOperation.F_EDIT, edits); + opOperation.setSignedBy(signed); + String hash = JSON_MSG_TYPE + ":" + + SecUtils.calculateHashWithAlgo(SecUtils.HASH_SHA256, null, + formatter.opToJsonNoHash(opOperation)); + byte[] hashBytes = SecUtils.getHashBytes(hash); + String signature = signMessageWithKeyBase64(kp, hashBytes, SecUtils.SIG_ALGO_SHA1_EC, null); + opOperation.addOrSetStringValue("hash", hash); + opOperation.addOrSetStringValue("signature", signature); + TrafficStats.setThreadStatsTag(THREAD_ID); + String url = baseUrl + "api/auth/process-operation?addToQueue=true&dontSignByServer=false"; + String json = formatter.opToJson(opOperation); + System.out.println("JSON: " + json); + HttpURLConnection connection; + try { + connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setConnectTimeout(10000); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + try { + DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); + wr.write(json.getBytes()); + } catch (Exception e) { + e.printStackTrace(); + } + int rc = connection.getResponseCode(); + if (rc != 200) { + log.error("ERROR HAPPENED"); + BufferedReader br = new BufferedReader(new InputStreamReader(connection.getErrorStream())); + String strCurrentLine; + while ((strCurrentLine = br.readLine()) != null) { + log.error(strCurrentLine); + sb.append(strCurrentLine); + } + } + return rc; + } catch (IOException e) { + log.error(e); + } + return -1; + } + + public class OPRImage { + public String type; + public String hash; + public String cid; + public String extension; + } +} diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java b/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java index d586516fc5..2e9e11c5c3 100644 --- a/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java +++ b/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java @@ -231,9 +231,8 @@ public class PoiFiltersHelper { public List getTopDefinedPoiFilters(boolean includeDeleted) { List top = this.cacheTopStandardFilters; if (top == null) { - top = new ArrayList<>(); // user defined - top.addAll(getUserDefinedPoiFilters(true)); + top = new ArrayList<>(getUserDefinedPoiFilters(true)); // default MapPoiTypes poiTypes = application.getPoiTypes(); for (AbstractPoiType t : poiTypes.getTopVisibleFilters()) { @@ -751,14 +750,15 @@ public class PoiFiltersHelper { } Map> types = p.getAcceptedTypes(); SQLiteStatement insertCategories = db.compileStatement("INSERT INTO " + CATEGORIES_NAME + " VALUES (?, ?, ?)"); - for (PoiCategory a : types.keySet()) { - if (types.get(a) == null) { + for (Map.Entry> entry : types.entrySet()) { + PoiCategory a = entry.getKey(); + if (entry.getValue() == null) { insertCategories.bindString(1, p.getFilterId()); insertCategories.bindString(2, a.getKeyName()); insertCategories.bindNull(3); insertCategories.execute(); } else { - for (String s : types.get(a)) { + for (String s : entry.getValue()) { insertCategories.bindString(1, p.getFilterId()); insertCategories.bindString(2, a.getKeyName()); insertCategories.bindString(3, s); diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java index 6629228696..1d3449640f 100644 --- a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java +++ b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java @@ -535,20 +535,19 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable return getName(); } StringBuilder res = new StringBuilder(); - for (PoiCategory p : acceptedTypes.keySet()) { - LinkedHashSet set = acceptedTypes.get(p); + for (Entry> entry : acceptedTypes.entrySet()) { + LinkedHashSet set = entry.getValue(); if (set == null) { if (res.length() > 0) { res.append(", "); } - res.append(p.getTranslation()); + res.append(entry.getKey().getTranslation()); } if (res.length() > chars) { return res.toString(); } } - for (PoiCategory p : acceptedTypes.keySet()) { - LinkedHashSet set = acceptedTypes.get(p); + for (LinkedHashSet set : acceptedTypes.values()) { if (set != null) { for (String st : set) { if (res.length() > 0) { @@ -616,8 +615,8 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable public boolean areAllTypesAccepted() { if (poiTypes.getCategories(false).size() == acceptedTypes.size()) { - for (PoiCategory a : acceptedTypes.keySet()) { - if (acceptedTypes.get(a) != null) { + for (LinkedHashSet strings : acceptedTypes.values()) { + if (strings != null) { return false; } } @@ -711,8 +710,9 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable } private void putAllAcceptedTypes(Map> types) { - for (PoiCategory category : types.keySet()) { - LinkedHashSet typesSet = types.get(category); + for (Entry> entry : types.entrySet()) { + PoiCategory category = entry.getKey(); + LinkedHashSet typesSet = entry.getValue(); if (acceptedTypes.containsKey(category)) { if (acceptedTypes.get(category) != null && typesSet != null) { acceptedTypes.get(category).addAll(typesSet); diff --git a/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java b/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java index 8bc8d1b51a..0b07a41c4f 100644 --- a/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java +++ b/OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java @@ -311,8 +311,9 @@ public class MapRenderRepositories { } boolean containsJapanMapData = false; boolean useLive = context.getSettings().USE_OSM_LIVE_FOR_ROUTING.get(); - for (String mapName : files.keySet()) { - BinaryMapIndexReader fr = files.get(mapName); + for (Map.Entry entry : files.entrySet()) { + String mapName = entry.getKey(); + BinaryMapIndexReader fr = entry.getValue(); if (fr != null && (fr.containsMapData(leftX, topY, rightX, bottomY, zoom) || fr.containsRouteData(leftX, topY, rightX, bottomY, zoom))) { if (!nativeFiles.contains(mapName)) { @@ -727,7 +728,7 @@ public class MapRenderRepositories { currentRenderingContext.height = requestedBox.getPixHeight(); currentRenderingContext.nightMode = nightMode; if(requestedBox.getZoom() <= zoomToOverviewLocalNames && - "".equals(prefs.MAP_PREFERRED_LOCALE.get())) { + prefs.MAP_PREFERRED_LOCALE.get() != null && prefs.MAP_PREFERRED_LOCALE.get().isEmpty()) { currentRenderingContext.preferredLocale = app.getLanguage(); currentRenderingContext.transliterate = !languagesNotTransliterateOnBasemap.contains(app.getLanguage()); diff --git a/OsmAnd/src/net/osmand/plus/render/TextRenderer.java b/OsmAnd/src/net/osmand/plus/render/TextRenderer.java index 9e338d08ec..f7bb2cd349 100644 --- a/OsmAnd/src/net/osmand/plus/render/TextRenderer.java +++ b/OsmAnd/src/net/osmand/plus/render/TextRenderer.java @@ -438,7 +438,7 @@ public class TextRenderer { String nameTag = isName ? "" : obj.getMapIndex().decodeType(tag).tag; boolean skip = false; // not completely correct we should check "name"+rc.preferredLocale - if (isName && !rc.preferredLocale.equals("") && + if (isName && !rc.preferredLocale.isEmpty() && map.containsKey(obj.getMapIndex().nameEnEncodingType)) { skip = true; } diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index a87d5004bd..8e7857b33a 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -486,7 +486,7 @@ public class ResourceManager { try { progress.startTask(context.getString(R.string.installing_new_resources), -1); AssetManager assetManager = context.getAssets(); - boolean isFirstInstall = context.getSettings().PREVIOUS_INSTALLED_VERSION.get().equals(""); + boolean isFirstInstall = context.getSettings().PREVIOUS_INSTALLED_VERSION.get().isEmpty(); unpackBundledAssets(assetManager, applicationDataDir, progress, isFirstInstall || forceUpdate); context.getSettings().PREVIOUS_INSTALLED_VERSION.set(fv); copyRegionsBoundaries(); @@ -1100,7 +1100,7 @@ public class ResourceManager { } } } - return readers.toArray(new BinaryMapIndexReader[readers.size()]); + return readers.toArray(new BinaryMapIndexReader[0]); } public BinaryMapIndexReader[] getTransportRoutingMapFiles() { @@ -1114,7 +1114,7 @@ public class ResourceManager { } } } - return readers.toArray(new BinaryMapIndexReader[readers.size()]); + return readers.toArray(new BinaryMapIndexReader[0]); } public BinaryMapIndexReader[] getQuickSearchFiles() { @@ -1129,7 +1129,7 @@ public class ResourceManager { } } } - return readers.toArray(new BinaryMapIndexReader[readers.size()]); + return readers.toArray(new BinaryMapIndexReader[0]); } public Map getIndexFileNames() { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/AddPointBottomSheetDialog.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/AddPointBottomSheetDialog.java index 7257e2ec00..7c70ba8dfb 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/AddPointBottomSheetDialog.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/AddPointBottomSheetDialog.java @@ -651,7 +651,7 @@ public class AddPointBottomSheetDialog extends MenuBottomSheetDialogFragment { ((FavouritePoint) item).getSpecialPointType().getIconId(app), iconColor)); favoriteViewHolder.description.setText(point.getDescription()); } else { - if (point.getCategory().equals("")) { + if (point.getCategory().isEmpty()) { favoriteViewHolder.description.setText(R.string.shared_string_favorites); } else { favoriteViewHolder.description.setText(point.getCategory()); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java index d805cde0df..7730010808 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java @@ -156,6 +156,7 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca if (view != null) { ImageButton closeButton = view.findViewById(R.id.close_button); buttonsShadow = view.findViewById(R.id.buttons_shadow); + sortButton = view.findViewById(R.id.sort_button); closeButton.setImageDrawable(getContentIcon(AndroidUtils.getNavigationIconResId(app))); closeButton.setOnClickListener(new View.OnClickListener() { @Override @@ -219,6 +220,7 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca if (Algorithms.isEmpty(fileName)) { fileName = app.getString(R.string.shared_string_gpx_track); } + sortButton.setVisibility(View.GONE); GPXInfo gpxInfo = new GPXInfo(fileName, file != null ? file.lastModified() : 0, file != null ? file.length() : 0); TrackEditCard importTrackCard = new TrackEditCard(mapActivity, gpxInfo); importTrackCard.setListener(this); @@ -268,6 +270,7 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca tracksCard = new TracksToFollowCard(mapActivity, list, defaultCategory); tracksCard.setListener(FollowTrackFragment.this); getCardsContainer().addView(tracksCard.build(mapActivity)); + sortButton.setVisibility(View.VISIBLE); } } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java index 780186b068..0747c650c5 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java @@ -27,8 +27,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; -import com.github.mikephil.charting.charts.LineChart; - import net.osmand.AndroidUtils; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXTrackAnalysis; @@ -41,7 +39,6 @@ import net.osmand.data.QuadRect; import net.osmand.data.TransportRoute; import net.osmand.data.TransportStop; import net.osmand.plus.GeocodingLookupService; -import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; @@ -82,8 +79,8 @@ import net.osmand.render.RenderingRulesStorage; import net.osmand.router.RouteSegmentResult; import net.osmand.router.RouteStatisticsHelper; import net.osmand.router.RouteStatisticsHelper.RouteStatistics; -import net.osmand.router.TransportRouteResult; import net.osmand.router.TransportRoutePlanner.TransportRouteResultSegment; +import net.osmand.router.TransportRouteResult; import net.osmand.util.Algorithms; import java.lang.ref.WeakReference; @@ -371,7 +368,9 @@ public class RouteDetailsFragment extends ContextMenuFragment protected void calculateLayout(View view, boolean initLayout) { super.calculateLayout(view, initLayout); if (!initLayout && getCurrentMenuState() != MenuState.FULL_SCREEN) { - refreshMapCallback.refreshMap(false); + if (refreshMapCallback != null) { + refreshMapCallback.refreshMap(false); + } } } diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index a21b8898e6..37bb29d148 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -121,7 +121,7 @@ public class RouteProvider { list.add(r); } } - return list.toArray(new RouteService[list.size()]); + return list.toArray(new RouteService[0]); } } diff --git a/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java b/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java index 3c55261668..9badea394e 100644 --- a/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java @@ -259,6 +259,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final MapActivity mapActivity = getMapActivity(); + final UiUtilities iconsCache = app.getUIUtilities(); final View view = inflater.inflate(R.layout.search_dialog_fragment, container, false); toolbarController = new QuickSearchToolbarController(); @@ -325,9 +326,9 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC buttonToolbarView = view.findViewById(R.id.button_toolbar_layout); buttonToolbarImage = (ImageView) view.findViewById(R.id.buttonToolbarImage); - buttonToolbarImage.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_marker_dark)); + buttonToolbarImage.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_marker_dark)); buttonToolbarFilter = (ImageButton) view.findViewById(R.id.filterButton); - buttonToolbarFilter.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_filter)); + buttonToolbarFilter.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_filter)); buttonToolbarFilter.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -474,7 +475,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC if (!app.getSettings().isLightContent()) { toolbar.setBackgroundColor(ContextCompat.getColor(mapActivity, R.color.app_bar_color_dark)); } - Drawable icBack = app.getUIUtilities().getThemedIcon(AndroidUtils.getNavigationIconResId(app)); + Drawable icBack = iconsCache.getThemedIcon(AndroidUtils.getNavigationIconResId(app)); toolbar.setNavigationIcon(icBack); toolbar.setNavigationContentDescription(R.string.access_shared_string_navigate_up); toolbar.setNavigationOnClickListener( @@ -489,7 +490,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC ); toolbarEdit = (Toolbar) view.findViewById(R.id.toolbar_edit); - toolbarEdit.setNavigationIcon(app.getUIUtilities().getIcon(R.drawable.ic_action_remove_dark)); + toolbarEdit.setNavigationIcon(iconsCache.getIcon(R.drawable.ic_action_remove_dark)); toolbarEdit.setNavigationContentDescription(R.string.shared_string_cancel); toolbarEdit.setNavigationOnClickListener( new OnClickListener() { @@ -501,8 +502,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC ); titleEdit = (TextView) view.findViewById(R.id.titleEdit); - Drawable shareIcon = app.getUIUtilities().getIcon(R.drawable.ic_action_gshare_dark, - nightMode ? R.color.text_color_secondary_dark : R.color.text_color_secondary_light); + Drawable shareIcon = iconsCache.getIcon(R.drawable.ic_action_gshare_dark, R.color.color_white); shareIcon = AndroidUtils.getDrawableForDirection(app, shareIcon); ImageView shareButton = (ImageView) view.findViewById(R.id.shareButton); shareButton.setImageDrawable(shareIcon); @@ -644,7 +644,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC progressBar = (ProgressBar) view.findViewById(R.id.searchProgressBar); clearButton = (ImageButton) view.findViewById(R.id.clearButton); - clearButton.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_remove_dark)); + clearButton.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_remove_dark)); clearButton.setOnClickListener( new OnClickListener() { @Override diff --git a/OsmAnd/src/net/osmand/plus/search/QuickSearchHelper.java b/OsmAnd/src/net/osmand/plus/search/QuickSearchHelper.java index 55da1967d0..1213f550c1 100644 --- a/OsmAnd/src/net/osmand/plus/search/QuickSearchHelper.java +++ b/OsmAnd/src/net/osmand/plus/search/QuickSearchHelper.java @@ -436,7 +436,12 @@ public class QuickSearchHelper implements ResourceListener { SearchResult sr = new SearchResult(phrase); PointDescription pd = point.getName(); if (pd.isPoiType()) { - AbstractPoiType pt = MapPoiTypes.getDefault().getAnyPoiTypeByKey(pd.getName()); + String name = pd.getName(); + MapPoiTypes mapPoiTypes = MapPoiTypes.getDefault(); + AbstractPoiType pt = mapPoiTypes.getAnyPoiTypeByKey(name); + if (pt == null) { + pt = mapPoiTypes.getAnyPoiAdditionalTypeByKey(name); + } if (pt != null) { sr.localeName = pt.getTranslation(); sr.object = pt; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java b/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java index bf86c42ee6..13135c0821 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java @@ -10,7 +10,6 @@ public enum ExportSettingsType { GLOBAL(R.string.general_settings_2, R.drawable.ic_action_settings), QUICK_ACTIONS(R.string.configure_screen_quick_action, R.drawable.ic_quick_action), POI_TYPES(R.string.poi_dialog_poi_type, R.drawable.ic_action_info_dark), - SEARCH_HISTORY(R.string.shared_string_search_history, R.drawable.ic_action_history), AVOID_ROADS(R.string.avoid_road, R.drawable.ic_action_alert), FAVORITES(R.string.shared_string_favorites, R.drawable.ic_action_favorite), TRACKS(R.string.shared_string_tracks, R.drawable.ic_action_route_distance), @@ -19,6 +18,7 @@ public enum ExportSettingsType { MULTIMEDIA_NOTES(R.string.audionotes_plugin_name, R.drawable.ic_grouped_by_type), ACTIVE_MARKERS(R.string.map_markers, R.drawable.ic_action_flag), HISTORY_MARKERS(R.string.markers_history, R.drawable.ic_action_flag), + SEARCH_HISTORY(R.string.shared_string_search_history, R.drawable.ic_action_history), CUSTOM_RENDER_STYLE(R.string.shared_string_rendering_style, R.drawable.ic_action_map_style), CUSTOM_ROUTING(R.string.shared_string_routing, R.drawable.ic_action_route_distance), MAP_SOURCES(R.string.quick_action_map_source_title, R.drawable.ic_map), @@ -48,12 +48,13 @@ public enum ExportSettingsType { public boolean isSettingsCategory() { return this == PROFILE || this == GLOBAL || this == QUICK_ACTIONS || this == POI_TYPES - || this == SEARCH_HISTORY || this == AVOID_ROADS; + || this == AVOID_ROADS; } public boolean isMyPlacesCategory() { return this == FAVORITES || this == TRACKS || this == OSM_EDITS || this == OSM_NOTES - || this == MULTIMEDIA_NOTES || this == ACTIVE_MARKERS || this == HISTORY_MARKERS; + || this == MULTIMEDIA_NOTES || this == ACTIVE_MARKERS || this == HISTORY_MARKERS + || this == SEARCH_HISTORY; } public boolean isResourcesCategory() { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index a574e0d0fd..065fd2113a 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -1133,6 +1133,17 @@ public class OsmandSettings { // this value boolean is synchronized with settings_pref.xml preference offline POI/Bugs edition public final OsmandPreference OFFLINE_EDITION = new BooleanPreference(this, "offline_osm_editing", true).makeGlobal().makeShared(); + public final OsmandPreference USE_DEV_URL = new BooleanPreference(this, "use_dev_url", false).makeGlobal().makeShared(); + + public String getOsmUrl() { + String osmUrl; + if (USE_DEV_URL.get()) { + osmUrl = "https://master.apis.dev.openstreetmap.org/"; + } else { + osmUrl = "https://api.openstreetmap.org/"; + } + return osmUrl; + } // this value string is synchronized with settings_pref.xml preference name public final CommonPreference DAYNIGHT_MODE = diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/CollectionSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/CollectionSettingsItem.java index dea9d51bc8..7140c7826b 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/CollectionSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/CollectionSettingsItem.java @@ -68,6 +68,10 @@ public abstract class CollectionSettingsItem extends SettingsItem { return res; } + public boolean shouldShowDuplicates() { + return true; + } + public abstract boolean isDuplicate(@NonNull T item); @NonNull 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 563a04fc75..493e49fa07 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -19,6 +19,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class FileSettingsItem extends StreamSettingsItem { @@ -131,6 +132,7 @@ public class FileSettingsItem extends StreamSettingsItem { private final File appPath; protected FileSubtype subtype; private long size; + private long lastModified; public FileSettingsItem(@NonNull OsmandApplication app, @NonNull File file) throws IllegalArgumentException { super(app, file.getPath().replace(app.getAppPath(null).getPath(), "")); @@ -222,6 +224,14 @@ public class FileSettingsItem extends StreamSettingsItem { this.size = size; } + public long getLastModified() { + return lastModified; + } + + public void setLastModified(long lastModified) { + this.lastModified = lastModified; + } + @NonNull public File getFile() { return file; @@ -292,6 +302,9 @@ public class FileSettingsItem extends StreamSettingsItem { } finally { Algorithms.closeStream(output); } + if (lastModified != -1) { + dest.setLastModified(lastModified); + } } }; } @@ -306,7 +319,14 @@ public class FileSettingsItem extends StreamSettingsItem { warnings.add(app.getString(R.string.settings_item_read_error, file.getName())); SettingsHelper.LOG.error("Failed to set input stream from file: " + file.getName(), e); } - return super.getWriter(); + return new StreamSettingsItemWriter(this) { + @Override + public ZipEntry createNewEntry(String fileName) { + ZipEntry entry = super.createNewEntry(fileName); + entry.setTime(file.lastModified()); + return entry; + } + }; } else { return new StreamSettingsItemWriter(this) { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/HistoryMarkersSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/HistoryMarkersSettingsItem.java index cc152f7ad3..9f441b7ec8 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/HistoryMarkersSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/HistoryMarkersSettingsItem.java @@ -87,7 +87,7 @@ public class HistoryMarkersSettingsItem extends CollectionSettingsItem { public boolean isDuplicate(@NonNull MapMarker mapMarker) { for (MapMarker marker : existingItems) { if (marker.equals(mapMarker) - && Algorithms.objectEquals(marker.getOriginalPointDescription(), mapMarker.getOriginalPointDescription())) { + && Algorithms.objectEquals(marker.getOnlyName(), mapMarker.getOnlyName())) { return true; } } @@ -114,10 +114,13 @@ public class MarkersSettingsItem extends CollectionSettingsItem { int number = 0; while (true) { number++; - String name = item.getOnlyName() + "_" + number; + String name = item.getOnlyName() + " " + number; PointDescription description = new PointDescription(PointDescription.POINT_TYPE_LOCATION, name); - MapMarker renamedMarker = new MapMarker(item.point, description, item.getColor(), item.selected, item.index); + MapMarker renamedMarker = new MapMarker(item.point, description, item.colorIndex, item.selected, item.index); if (!isDuplicate(renamedMarker)) { + renamedMarker.history = false; + renamedMarker.visitedDate = item.visitedDate; + renamedMarker.creationDate = item.creationDate; renamedMarker.nextKey = MapMarkersDbHelper.TAIL_NEXT_VALUE; return renamedMarker; } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SearchHistorySettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SearchHistorySettingsItem.java index a4af84f7ca..70e5db4ba5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SearchHistorySettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SearchHistorySettingsItem.java @@ -143,6 +143,11 @@ public class SearchHistorySettingsItem extends CollectionSettingsItem) { - List duplicates = ((CollectionSettingsItem) item).processDuplicateItems(); - if (!duplicates.isEmpty()) { + CollectionSettingsItem settingsItem = (CollectionSettingsItem) item; + List duplicates = settingsItem.processDuplicateItems(); + if (!duplicates.isEmpty() && settingsItem.shouldShowDuplicates()) { duplicateItems.addAll(duplicates); } } else if (item instanceof FileSettingsItem) { @@ -471,13 +473,11 @@ public class SettingsHelper { } public List getFilteredSettingsItems(List settingsTypes, boolean globalExport) { - Map> dataList = getAdditionalData(globalExport); Map> typesMap = new HashMap<>(); - for (List objects : dataList.values()) { - for (ExportDataObject exportObject : objects) { - typesMap.put(exportObject.getType(), exportObject.getItems()); - } - } + typesMap.putAll(getSettingsItems(globalExport)); + typesMap.putAll(getMyPlacesItems()); + typesMap.putAll(getResourcesItems()); + return getFilteredSettingsItems(typesMap, settingsTypes); } @@ -498,67 +498,60 @@ public class SettingsHelper { return settingsItems; } - public Map> getAdditionalData(boolean globalExport) { - Map> dataList = new LinkedHashMap<>(); + public Map getAdditionalData(boolean globalExport) { + Map dataList = new LinkedHashMap<>(); - List settingsItems = getSettingsItems(globalExport); - List myPlacesItems = getMyPlacesItems(); - List resourcesItems = getResourcesItems(); + Map> settingsItems = getSettingsItems(globalExport); + Map> myPlacesItems = getMyPlacesItems(); + Map> resourcesItems = getResourcesItems(); if (!settingsItems.isEmpty()) { - sortExportSettingsObjects(settingsItems); - dataList.put(ExportSettingsCategory.SETTINGS, settingsItems); + dataList.put(ExportSettingsCategory.SETTINGS, new SettingsCategoryItems(settingsItems)); } if (!myPlacesItems.isEmpty()) { - sortExportSettingsObjects(myPlacesItems); - dataList.put(ExportSettingsCategory.MY_PLACES, myPlacesItems); + dataList.put(ExportSettingsCategory.MY_PLACES, new SettingsCategoryItems(myPlacesItems)); } if (!resourcesItems.isEmpty()) { - sortExportSettingsObjects(resourcesItems); - dataList.put(ExportSettingsCategory.RESOURCES, resourcesItems); + dataList.put(ExportSettingsCategory.RESOURCES, new SettingsCategoryItems(resourcesItems)); } return dataList; } - private List getSettingsItems(boolean globalExport) { - List settingsItems = new ArrayList<>(); + private Map> getSettingsItems(boolean globalExport) { + Map> settingsItems = new LinkedHashMap<>(); if (globalExport) { List appModeBeans = new ArrayList<>(); for (ApplicationMode mode : ApplicationMode.allPossibleValues()) { appModeBeans.add(mode.toModeBean()); } - settingsItems.add(new ExportDataObject(ExportSettingsType.PROFILE, appModeBeans)); + settingsItems.put(ExportSettingsType.PROFILE, appModeBeans); } - settingsItems.add(new ExportDataObject(ExportSettingsType.GLOBAL, Collections.singletonList(new GlobalSettingsItem(app.getSettings())))); + settingsItems.put(ExportSettingsType.GLOBAL, Collections.singletonList(new GlobalSettingsItem(app.getSettings()))); QuickActionRegistry registry = app.getQuickActionRegistry(); List actionsList = registry.getQuickActions(); if (!actionsList.isEmpty()) { - settingsItems.add(new ExportDataObject(ExportSettingsType.QUICK_ACTIONS, actionsList)); + settingsItems.put(ExportSettingsType.QUICK_ACTIONS, actionsList); } List poiList = app.getPoiFilters().getUserDefinedPoiFilters(false); if (!poiList.isEmpty()) { - settingsItems.add(new ExportDataObject(ExportSettingsType.POI_TYPES, poiList)); - } - List historyEntries = SearchHistoryHelper.getInstance(app).getHistoryEntries(false); - if (!historyEntries.isEmpty()) { - settingsItems.add(new ExportDataObject(ExportSettingsType.SEARCH_HISTORY, historyEntries)); + settingsItems.put(ExportSettingsType.POI_TYPES, poiList); } Map impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads(); if (!impassableRoads.isEmpty()) { - settingsItems.add(new ExportDataObject(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values()))); + settingsItems.put(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values())); } return settingsItems; } - private List getMyPlacesItems() { - List myPlacesItems = new ArrayList<>(); + private Map> getMyPlacesItems() { + Map> myPlacesItems = new LinkedHashMap<>(); List favoriteGroups = app.getFavorites().getFavoriteGroups(); if (!favoriteGroups.isEmpty()) { - myPlacesItems.add(new ExportDataObject(ExportSettingsType.FAVORITES, favoriteGroups)); + myPlacesItems.put(ExportSettingsType.FAVORITES, favoriteGroups); } File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR); List gpxInfoList = GpxUiHelper.getSortedGPXFilesInfo(gpxDir, null, true); @@ -571,18 +564,18 @@ public class SettingsHelper { } } if (!files.isEmpty()) { - myPlacesItems.add(new ExportDataObject(ExportSettingsType.TRACKS, files)); + myPlacesItems.put(ExportSettingsType.TRACKS, files); } } OsmEditingPlugin osmEditingPlugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class); if (osmEditingPlugin != null) { List notesPointList = osmEditingPlugin.getDBBug().getOsmbugsPoints(); if (!notesPointList.isEmpty()) { - myPlacesItems.add(new ExportDataObject(ExportSettingsType.OSM_NOTES, notesPointList)); + myPlacesItems.put(ExportSettingsType.OSM_NOTES, notesPointList); } List editsPointList = osmEditingPlugin.getDBPOI().getOpenstreetmapPoints(); if (!editsPointList.isEmpty()) { - myPlacesItems.add(new ExportDataObject(ExportSettingsType.OSM_EDITS, editsPointList)); + myPlacesItems.put(ExportSettingsType.OSM_EDITS, editsPointList); } } AudioVideoNotesPlugin plugin = OsmandPlugin.getPlugin(AudioVideoNotesPlugin.class); @@ -595,7 +588,7 @@ public class SettingsHelper { } } if (!files.isEmpty()) { - myPlacesItems.add(new ExportDataObject(ExportSettingsType.MULTIMEDIA_NOTES, files)); + myPlacesItems.put(ExportSettingsType.MULTIMEDIA_NOTES, files); } } List mapMarkers = app.getMapMarkersHelper().getMapMarkersFromDefaultGroups(false); @@ -604,7 +597,7 @@ public class SettingsHelper { String groupId = ExportSettingsType.ACTIVE_MARKERS.name(); MapMarkersGroup markersGroup = new MapMarkersGroup(groupId, name, MapMarkersGroup.ANY_TYPE); markersGroup.setMarkers(mapMarkers); - myPlacesItems.add(new ExportDataObject(ExportSettingsType.ACTIVE_MARKERS, Collections.singletonList(markersGroup))); + myPlacesItems.put(ExportSettingsType.ACTIVE_MARKERS, Collections.singletonList(markersGroup)); } List markersHistory = app.getMapMarkersHelper().getMapMarkersFromDefaultGroups(true); if (!markersHistory.isEmpty()) { @@ -612,23 +605,27 @@ public class SettingsHelper { String groupId = ExportSettingsType.HISTORY_MARKERS.name(); MapMarkersGroup markersGroup = new MapMarkersGroup(groupId, name, MapMarkersGroup.ANY_TYPE); markersGroup.setMarkers(markersHistory); - myPlacesItems.add(new ExportDataObject(ExportSettingsType.HISTORY_MARKERS, Collections.singletonList(markersGroup))); + myPlacesItems.put(ExportSettingsType.HISTORY_MARKERS, Collections.singletonList(markersGroup)); + } + List historyEntries = SearchHistoryHelper.getInstance(app).getHistoryEntries(false); + if (!historyEntries.isEmpty()) { + myPlacesItems.put(ExportSettingsType.SEARCH_HISTORY, historyEntries); } return myPlacesItems; } - private List getResourcesItems() { - List resourcesItems = new ArrayList<>(); + private Map> getResourcesItems() { + Map> resourcesItems = new LinkedHashMap<>(); Map externalRenderers = app.getRendererRegistry().getExternalRenderers(); if (!externalRenderers.isEmpty()) { - resourcesItems.add(new ExportDataObject(ExportSettingsType.CUSTOM_RENDER_STYLE, new ArrayList<>(externalRenderers.values()))); + resourcesItems.put(ExportSettingsType.CUSTOM_RENDER_STYLE, new ArrayList<>(externalRenderers.values())); } File routingProfilesFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR); if (routingProfilesFolder.exists() && routingProfilesFolder.isDirectory()) { File[] fl = routingProfilesFolder.listFiles(); if (fl != null && fl.length > 0) { - resourcesItems.add(new ExportDataObject(ExportSettingsType.CUSTOM_ROUTING, Arrays.asList(fl))); + resourcesItems.put(ExportSettingsType.CUSTOM_ROUTING, Arrays.asList(fl)); } } List iTileSources = new ArrayList<>(); @@ -648,22 +645,22 @@ public class SettingsHelper { } } if (!iTileSources.isEmpty()) { - resourcesItems.add(new ExportDataObject(ExportSettingsType.MAP_SOURCES, iTileSources)); + resourcesItems.put(ExportSettingsType.MAP_SOURCES, iTileSources); } List localIndexInfoList = getLocalIndexData(); List files = getFilesByType(localIndexInfoList, LocalIndexType.MAP_DATA, LocalIndexType.TILES_DATA, LocalIndexType.SRTM_DATA, LocalIndexType.WIKI_DATA); if (!files.isEmpty()) { sortLocalFiles(files); - resourcesItems.add(new ExportDataObject(ExportSettingsType.OFFLINE_MAPS, files)); + resourcesItems.put(ExportSettingsType.OFFLINE_MAPS, files); } files = getFilesByType(localIndexInfoList, LocalIndexType.TTS_VOICE_DATA); if (!files.isEmpty()) { - resourcesItems.add(new ExportDataObject(ExportSettingsType.TTS_VOICE, files)); + resourcesItems.put(ExportSettingsType.TTS_VOICE, files); } files = getFilesByType(localIndexInfoList, LocalIndexType.VOICE_DATA); if (!files.isEmpty()) { - resourcesItems.add(new ExportDataObject(ExportSettingsType.VOICE, files)); + resourcesItems.put(ExportSettingsType.VOICE, files); } return resourcesItems; @@ -792,42 +789,39 @@ public class SettingsHelper { return settingsItems; } - public static Map> getSettingsToOperateByCategory(List items, boolean importComplete) { - Map> exportMap = new LinkedHashMap<>(); + public static Map getSettingsToOperateByCategory(List items, boolean importComplete) { + Map exportMap = new LinkedHashMap<>(); Map> settingsToOperate = getSettingsToOperate(items, importComplete); - List settingsItems = new ArrayList<>(); - List myPlacesItems = new ArrayList<>(); - List resourcesItems = new ArrayList<>(); + Map> settingsItems = new LinkedHashMap<>(); + Map> myPlacesItems = new LinkedHashMap<>(); + Map> resourcesItems = new LinkedHashMap<>(); for (Map.Entry> entry : settingsToOperate.entrySet()) { ExportSettingsType type = entry.getKey(); if (type.isSettingsCategory()) { - settingsItems.add(new ExportDataObject(type, entry.getValue())); + settingsItems.put(type, entry.getValue()); } else if (type.isMyPlacesCategory()) { - myPlacesItems.add(new ExportDataObject(type, entry.getValue())); + myPlacesItems.put(type, entry.getValue()); } else if (type.isResourcesCategory()) { - resourcesItems.add(new ExportDataObject(type, entry.getValue())); + resourcesItems.put(type, entry.getValue()); } } if (!settingsItems.isEmpty()) { - sortExportSettingsObjects(settingsItems); - exportMap.put(ExportSettingsCategory.SETTINGS, settingsItems); + exportMap.put(ExportSettingsCategory.SETTINGS, new SettingsCategoryItems(settingsItems)); } if (!myPlacesItems.isEmpty()) { - sortExportSettingsObjects(myPlacesItems); - exportMap.put(ExportSettingsCategory.MY_PLACES, myPlacesItems); + exportMap.put(ExportSettingsCategory.MY_PLACES, new SettingsCategoryItems(myPlacesItems)); } if (!resourcesItems.isEmpty()) { - sortExportSettingsObjects(resourcesItems); - exportMap.put(ExportSettingsCategory.RESOURCES, resourcesItems); + exportMap.put(ExportSettingsCategory.RESOURCES, new SettingsCategoryItems(resourcesItems)); } return exportMap; } public static Map> getSettingsToOperate(List settingsItems, boolean importComplete) { - Map> settingsToOperate = new HashMap<>(); + Map> settingsToOperate = new EnumMap<>(ExportSettingsType.class); List profiles = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); @@ -835,10 +829,10 @@ public class SettingsHelper { List routingFilesList = new ArrayList<>(); 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 tracksFilesList = new ArrayList<>(); List avoidRoads = new ArrayList<>(); List globalSettingsItems = new ArrayList<>(); List notesPointList = new ArrayList<>(); @@ -862,7 +856,7 @@ public class SettingsHelper { } else if (fileItem.getSubtype() == FileSubtype.MULTIMEDIA_NOTES) { multimediaFilesList.add(fileItem.getFile()); } else if (fileItem.getSubtype() == FileSubtype.GPX) { - tracksFilesList.add(fileItem.getFile()); + tracksFilesList.add(fileItem); } else if (fileItem.getSubtype().isMap()) { mapFilesList.add(fileItem); } else if (fileItem.getSubtype() == FileSubtype.TTS_VOICE) { @@ -1016,15 +1010,4 @@ public class SettingsHelper { } }); } - - private static void sortExportSettingsObjects(List items) { - Collections.sort(items, new Comparator() { - @Override - public int compare(ExportDataObject lhs, ExportDataObject rhs) { - int order1 = lhs.getType().ordinal(); - int order2 = rhs.getType().ordinal(); - return (order1 < order2) ? -1 : ((order1 == order2) ? 0 : 1); - } - }); - } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java index 7f72761066..66c40d03cc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsImporter.java @@ -60,7 +60,7 @@ class SettingsImporter { try { SettingsItemsFactory itemsFactory = new SettingsItemsFactory(app, itemsJson); List settingsItemList = itemsFactory.getItems(); - getFilesSize(file, settingsItemList); + updateFilesInfo(file, settingsItemList); items.addAll(settingsItemList); } catch (IllegalArgumentException e) { SettingsHelper.LOG.error("Error parsing items: " + itemsJson, e); @@ -81,7 +81,7 @@ class SettingsImporter { return items; } - private void getFilesSize(@NonNull File file, List settingsItemList) throws IOException { + private void updateFilesInfo(@NonNull File file, List settingsItemList) throws IOException { ZipFile zipfile = new ZipFile(file.getPath()); Enumeration zipEnum = zipfile.entries(); while (zipEnum.hasMoreElements()) { @@ -90,7 +90,9 @@ class SettingsImporter { for (SettingsItem settingsItem : settingsItemList) { if (settingsItem instanceof FileSettingsItem && zipEntry.getName().equals(settingsItem.getFileName())) { - ((FileSettingsItem) settingsItem).setSize(size); + FileSettingsItem fileSettingsItem = (FileSettingsItem) settingsItem; + fileSettingsItem.setSize(size); + fileSettingsItem.setLastModified(zipEntry.getTime()); break; } } 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 090767a493..65863f0e90 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemWriter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsItemWriter.java @@ -22,9 +22,13 @@ 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); + ZipEntry entry = createNewEntry(fileName); zos.putNextEntry(entry); writeToStream(zos); zos.closeEntry(); } + + public ZipEntry createNewEntry(String fileName) { + return new ZipEntry(fileName); + } } diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BooleanPreferenceBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BooleanPreferenceBottomSheet.java index f34d6938fb..3730833d4d 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BooleanPreferenceBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/BooleanPreferenceBottomSheet.java @@ -59,9 +59,9 @@ public class BooleanPreferenceBottomSheet extends BasePreferenceBottomSheet { final BooleanPreference pref = (BooleanPreference) preference; CharSequence summaryOn = switchPreference.getSummaryOn(); CharSequence summaryOff = switchPreference.getSummaryOff(); - final String on = summaryOn == null || summaryOn.toString().equals("") + final String on = summaryOn == null || summaryOn.toString().isEmpty() ? getString(R.string.shared_string_enabled) : summaryOn.toString(); - final String off = summaryOff == null || summaryOff.toString().equals("") + final String off = summaryOff == null || summaryOff.toString().isEmpty() ? getString(R.string.shared_string_disabled) : summaryOff.toString(); final int activeColor = AndroidUtils.resolveAttribute(themedCtx, R.attr.active_color_basic); final int disabledColor = AndroidUtils.resolveAttribute(themedCtx, android.R.attr.textColorSecondary); diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java index 169d89b8cd..622fc11977 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java @@ -47,8 +47,6 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet { userNameEditText = view.findViewById(R.id.name_edit_text); passwordEditText = view.findViewById(R.id.password_edit_text); - userNameEditText.setBackgroundColor(getResolvedColor(R.color.background_field)); - passwordEditText.setBackgroundColor(getResolvedColor(R.color.background_field)); String name = app.getSettings().USER_NAME.get(); String password = app.getSettings().USER_PASSWORD.get(); @@ -64,11 +62,6 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet { TextInputLayout loginBox = view.findViewById(R.id.name_text_box); TextInputLayout passwordBox = view.findViewById(R.id.password_text_box); - loginBox.setBoxStrokeColor(getResolvedColor(R.color.osmand_orange)); - loginBox.setHintTextColor(AppCompatResources.getColorStateList(getContext(),R.color.hint_label)); - passwordBox.setBoxStrokeColor(getResolvedColor(R.color.osmand_orange)); - passwordBox.setHintTextColor(AppCompatResources.getColorStateList(getContext(),R.color.hint_label)); - passwordBox.setStartIconDrawable(R.drawable.ic_action_lock); loginBox.setStartIconDrawable(R.drawable.ic_action_user_account); loginBox.setEndIconMode(TextInputLayout.END_ICON_CLEAR_TEXT); diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/SelectFolderBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/SelectFolderBottomSheet.java index 6a3cc193b2..10c09021b9 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/SelectFolderBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/SelectFolderBottomSheet.java @@ -158,7 +158,7 @@ public class SelectFolderBottomSheet extends BasePreferenceBottomSheet { Fragment fragment = getTargetFragment(); if (fragment instanceof BaseSettingsFragment) { String newPath = editText.getText().toString().trim(); - if (!newPath.equals("")) { + if (!newPath.isEmpty()) { boolean pathChanged = !newPath.equals(currentPath); Bundle bundle = new Bundle(); bundle.putBoolean(TAG, true); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsListFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsListFragment.java new file mode 100644 index 0000000000..86b7389f6e --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsListFragment.java @@ -0,0 +1,292 @@ +package net.osmand.plus.settings.fragments; + +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ExpandableListView; +import android.widget.LinearLayout; + +import androidx.activity.OnBackPressedCallback; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.Toolbar; +import androidx.core.view.ViewCompat; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import net.osmand.AndroidUtils; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.UiUtilities.DialogButtonType; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.settings.backend.ExportSettingsCategory; +import net.osmand.plus.settings.backend.ExportSettingsType; +import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener; +import net.osmand.plus.widgets.TextViewEx; +import net.osmand.util.Algorithms; + +import java.io.File; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implements OnItemSelectedListener { + + protected static final String SETTINGS_LIST_TAG = "settings_list_tag"; + + protected OsmandApplication app; + + protected Map> selectedItemsMap = new EnumMap<>(ExportSettingsType.class); + protected Map dataList = new LinkedHashMap<>(); + + protected View header; + protected View continueBtn; + protected View headerShadow; + protected View headerDivider; + protected View itemsSizeContainer; + protected View availableSpaceContainer; + protected TextViewEx selectedItemsSize; + protected TextViewEx availableSpaceDescr; + protected LinearLayout buttonsContainer; + protected ExpandableListView expandableList; + protected ExportSettingsAdapter adapter; + + protected boolean exportMode; + protected boolean nightMode; + private boolean wasDrawerDisabled; + + @Override + public int getStatusBarColorId() { + return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + app = requireMyApplication(); + nightMode = !app.getSettings().isLightContent(); + + requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + if (hasSelectedData()) { + showExitDialog(); + } else { + dismissFragment(); + } + } + }); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + LayoutInflater themedInflater = UiUtilities.getInflater(app, nightMode); + View root = themedInflater.inflate(R.layout.fragment_import, container, false); + AndroidUtils.addStatusBarPadding21v(app, root); + + selectedItemsSize = root.findViewById(R.id.file_size); + itemsSizeContainer = root.findViewById(R.id.file_size_container); + expandableList = root.findViewById(R.id.list); + buttonsContainer = root.findViewById(R.id.buttons_container); + + Toolbar toolbar = root.findViewById(R.id.toolbar); + setupToolbar(toolbar); + ViewCompat.setNestedScrollingEnabled(expandableList, true); + + header = themedInflater.inflate(R.layout.list_item_description_header, null); + headerDivider = header.findViewById(R.id.divider); + headerShadow = header.findViewById(R.id.card_bottom_divider); + expandableList.addHeaderView(header); + + availableSpaceContainer = themedInflater.inflate(R.layout.enough_space_warning_card, null); + availableSpaceDescr = availableSpaceContainer.findViewById(R.id.warning_descr); + + continueBtn = root.findViewById(R.id.continue_button); + UiUtilities.setupDialogButton(nightMode, continueBtn, DialogButtonType.PRIMARY, getString(R.string.shared_string_continue)); + root.findViewById(R.id.continue_button_container).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (expandableList.getHeaderViewsCount() <= 1) { + if (hasSelectedData()) { + onContinueButtonClickAction(); + } + } else { + expandableList.smoothScrollToPosition(0); + } + } + }); + + adapter = new ExportSettingsAdapter(app, this, nightMode); + adapter.updateSettingsItems(dataList, selectedItemsMap); + expandableList.setAdapter(adapter); + updateAvailableSpace(); + + return root; + } + + protected abstract void onContinueButtonClickAction(); + + @Override + public void onResume() { + super.onResume(); + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + wasDrawerDisabled = mapActivity.isDrawerDisabled(); + if (!wasDrawerDisabled) { + mapActivity.disableDrawer(); + } + } + } + + public void onPause() { + super.onPause(); + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null && !wasDrawerDisabled) { + mapActivity.enableDrawer(); + } + } + + protected void dismissFragment() { + FragmentManager fm = getFragmentManager(); + if (fm != null && !fm.isStateSaved()) { + getFragmentManager().popBackStack(SETTINGS_LIST_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); + } + } + + public void showExitDialog() { + Context themedContext = UiUtilities.getThemedContext(getActivity(), nightMode); + AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext); + dismissDialog.setTitle(getString(R.string.shared_string_dismiss)); + dismissDialog.setMessage(getString(R.string.exit_without_saving)); + dismissDialog.setNegativeButton(R.string.shared_string_cancel, null); + dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dismissFragment(); + } + }); + dismissDialog.show(); + } + + private void setupToolbar(Toolbar toolbar) { + toolbar.setNavigationIcon(getPaintedContentIcon(R.drawable.ic_action_close, nightMode + ? getResources().getColor(R.color.active_buttons_and_links_text_dark) + : getResources().getColor(R.color.active_buttons_and_links_text_light))); + toolbar.setNavigationContentDescription(R.string.shared_string_close); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (hasSelectedData()) { + showExitDialog(); + } else { + dismissFragment(); + } + } + }); + } + + protected void updateAvailableSpace() { + long calculatedSize = ExportSettingsAdapter.calculateItemsSize(adapter.getData()); + if (calculatedSize != 0) { + selectedItemsSize.setText(AndroidUtils.formatSize(app, calculatedSize)); + + File dir = app.getAppPath("").getParentFile(); + long availableSizeBytes = AndroidUtils.getAvailableSpace(dir); + if (calculatedSize > availableSizeBytes) { + String availableSize = AndroidUtils.formatSize(app, availableSizeBytes); + availableSpaceDescr.setText(getString(R.string.export_not_enough_space_descr, availableSize)); + updateWarningHeaderVisibility(true); + continueBtn.setEnabled(false); + } else { + updateWarningHeaderVisibility(false); + continueBtn.setEnabled(hasSelectedData()); + } + itemsSizeContainer.setVisibility(View.VISIBLE); + } else { + updateWarningHeaderVisibility(false); + itemsSizeContainer.setVisibility(View.INVISIBLE); + continueBtn.setEnabled(hasSelectedData()); + } + } + + public boolean hasSelectedData() { + for (List items : selectedItemsMap.values()) { + if (!Algorithms.isEmpty(items)) { + return true; + } + } + return false; + } + + private void updateWarningHeaderVisibility(boolean visible) { + if (visible) { + if (expandableList.getHeaderViewsCount() < 2) { + expandableList.addHeaderView(availableSpaceContainer); + } + AndroidUiHelper.updateVisibility(headerShadow, false); + AndroidUiHelper.updateVisibility(headerDivider, true); + } else { + expandableList.removeHeaderView(availableSpaceContainer); + AndroidUiHelper.updateVisibility(headerShadow, true); + AndroidUiHelper.updateVisibility(headerDivider, false); + } + } + + @Nullable + public MapActivity getMapActivity() { + FragmentActivity activity = getActivity(); + if (activity instanceof MapActivity) { + return (MapActivity) activity; + } else { + return null; + } + } + + @Override + public void onCategorySelected(ExportSettingsCategory category, boolean selected) { + SettingsCategoryItems categoryItems = dataList.get(category); + for (ExportSettingsType type : categoryItems.getTypes()) { + List selectedItems = selected ? categoryItems.getItemsForType(type) : new ArrayList<>(); + selectedItemsMap.put(type, selectedItems); + } + updateAvailableSpace(); + } + + @Override + public void onItemsSelected(ExportSettingsType type, List selectedItems) { + selectedItemsMap.put(type, selectedItems); + adapter.notifyDataSetChanged(); + updateAvailableSpace(); + } + + protected List getItemsForType(ExportSettingsType type) { + for (SettingsCategoryItems categoryItems : dataList.values()) { + if (categoryItems.getTypes().contains(type)) { + return (List) categoryItems.getItemsForType(type); + } + } + return null; + } + + protected List getSelectedItemsForType(ExportSettingsType type) { + return (List) selectedItemsMap.get(type); + } + + @Override + public void onTypeClicked(ExportSettingsType type) { + FragmentManager fragmentManager = getFragmentManager(); + if (fragmentManager != null && type != ExportSettingsType.GLOBAL && type != ExportSettingsType.SEARCH_HISTORY) { + ExportItemsBottomSheet.showInstance(fragmentManager, type, this, exportMode); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageFragment.java index 842b53e2fa..de95eaeade 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageFragment.java @@ -241,7 +241,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto divider.setVisibility(View.VISIBLE); secondPart.setVisibility(View.VISIBLE); String space = getSpaceDescription(item.getDirectory()); - if (!space.equals("")) { + if (!space.isEmpty()) { space = space.replaceAll(" • ", " • "); tvSummary.setText(space); tvSummary.setVisibility(View.VISIBLE); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java index 252b685bfc..fc6982a7a6 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java @@ -14,22 +14,22 @@ import net.osmand.IndexConstants; 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.helpers.SearchHistoryHelper.HistoryEntry; -import net.osmand.plus.settings.backend.ApplicationMode; -import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; +import net.osmand.plus.audionotes.AudioVideoNotesPlugin; import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; -import net.osmand.plus.mapmarkers.MapMarkersGroup; +import net.osmand.plus.helpers.FileNameTranslationHelper; +import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry; +import net.osmand.plus.mapmarkers.MapMarker; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.profiles.ProfileIconColors; import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.render.RenderingIcons; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -157,9 +157,9 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter items; - - public ExportDataObject(@NonNull ExportSettingsType type, @NonNull List items) { - this.type = type; - this.items = items; - } - - public ExportSettingsType getType() { - return type; - } - - public List getItems() { - return items; - } -} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java deleted file mode 100644 index 2643b5230d..0000000000 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java +++ /dev/null @@ -1,463 +0,0 @@ -package net.osmand.plus.settings.fragments; - -import android.content.res.ColorStateList; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.core.content.ContextCompat; -import androidx.core.widget.CompoundButtonCompat; - -import net.osmand.AndroidUtils; -import net.osmand.IndexConstants; -import net.osmand.PlatformUtil; -import net.osmand.map.ITileSource; -import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.R; -import net.osmand.plus.UiUtilities; -import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; -import net.osmand.plus.audionotes.AudioVideoNotesPlugin; -import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; -import net.osmand.plus.helpers.FileNameTranslationHelper; -import net.osmand.plus.helpers.GpxUiHelper; -import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry; -import net.osmand.plus.osmedit.OpenstreetmapPoint; -import net.osmand.plus.osmedit.OsmEditingPlugin; -import net.osmand.plus.osmedit.OsmNotesPoint; -import net.osmand.plus.poi.PoiUIFilter; -import net.osmand.plus.profiles.ProfileIconColors; -import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources; -import net.osmand.plus.quickaction.QuickAction; -import net.osmand.plus.render.RenderingIcons; -import net.osmand.plus.settings.backend.ApplicationMode; -import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; -import net.osmand.plus.settings.backend.ExportSettingsType; -import net.osmand.plus.settings.backend.backup.FileSettingsItem; -import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; -import net.osmand.util.Algorithms; -import net.osmand.view.ThreeStateCheckbox; - -import org.apache.commons.logging.Log; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static net.osmand.plus.settings.backend.ExportSettingsType.OFFLINE_MAPS; -import static net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype; -import static net.osmand.view.ThreeStateCheckbox.State.CHECKED; -import static net.osmand.view.ThreeStateCheckbox.State.MISC; -import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED; - -class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { - - private static final Log LOG = PlatformUtil.getLog(ExportImportSettingsAdapter.class.getName()); - private OsmandApplication app; - private UiUtilities uiUtilities; - private List data; - private Map> itemsMap; - private List itemsTypes; - private boolean nightMode; - private boolean importState; - private int activeColorRes; - private int secondaryColorRes; - - ExportImportSettingsAdapter(OsmandApplication app, boolean nightMode, boolean importState) { - this.app = app; - this.nightMode = nightMode; - this.importState = importState; - this.itemsMap = new HashMap<>(); - this.itemsTypes = new ArrayList<>(); - this.data = new ArrayList<>(); - uiUtilities = app.getUIUtilities(); - activeColorRes = nightMode - ? R.color.icon_color_active_dark - : R.color.icon_color_active_light; - secondaryColorRes = nightMode - ? R.color.icon_color_secondary_dark - : R.color.icon_color_secondary_light; - } - - @Override - public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { - View group = convertView; - if (group == null) { - LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); - group = inflater.inflate(R.layout.profile_data_list_item_group, parent, false); - } - - boolean isLastGroup = groupPosition == getGroupCount() - 1; - final ExportSettingsType type = itemsTypes.get(groupPosition); - - TextView titleTv = group.findViewById(R.id.title_tv); - TextView subTextTv = group.findViewById(R.id.sub_text_tv); - final ThreeStateCheckbox checkBox = group.findViewById(R.id.check_box); - FrameLayout checkBoxContainer = group.findViewById(R.id.check_box_container); - ImageView expandIv = group.findViewById(R.id.explist_indicator); - View lineDivider = group.findViewById(R.id.divider); - View cardTopDivider = group.findViewById(R.id.card_top_divider); - View cardBottomDivider = group.findViewById(R.id.card_bottom_divider); - - titleTv.setText(getGroupTitle(type)); - lineDivider.setVisibility(importState || isExpanded || isLastGroup ? View.GONE : View.VISIBLE); - cardTopDivider.setVisibility(importState ? View.VISIBLE : View.GONE); - cardBottomDivider.setVisibility(importState && !isExpanded ? View.VISIBLE : View.GONE); - - final List listItems = itemsMap.get(type); - subTextTv.setText(getSelectedItemsAmount(listItems, type)); - - if (data.containsAll(listItems)) { - checkBox.setState(CHECKED); - } else { - boolean contains = false; - for (Object object : listItems) { - if (data.contains(object)) { - contains = true; - break; - } - } - checkBox.setState(contains ? MISC : UNCHECKED); - } - int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; - CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); - checkBoxContainer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - checkBox.performClick(); - if (checkBox.getState() == CHECKED) { - for (Object object : listItems) { - if (!data.contains(object)) { - data.add(object); - } - } - } else { - data.removeAll(listItems); - } - notifyDataSetChanged(); - } - }); - adjustIndicator(app, groupPosition, isExpanded, group, nightMode); - return group; - } - - @Override - public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { - View child = convertView; - if (child == null) { - LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); - child = inflater.inflate(R.layout.profile_data_list_item_child, parent, false); - } - final Object currentItem = itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); - - boolean isLastGroup = groupPosition == getGroupCount() - 1; - boolean itemSelected = data.contains(currentItem); - final ExportSettingsType type = itemsTypes.get(groupPosition); - - TextView title = child.findViewById(R.id.title_tv); - TextView subText = child.findViewById(R.id.sub_title_tv); - subText.setVisibility(View.GONE); - final CheckBox checkBox = child.findViewById(R.id.check_box); - ImageView icon = child.findViewById(R.id.icon); - View lineDivider = child.findViewById(R.id.divider); - View cardBottomDivider = child.findViewById(R.id.card_bottom_divider); - - lineDivider.setVisibility(!importState && isLastChild && !isLastGroup ? View.VISIBLE : View.GONE); - cardBottomDivider.setVisibility(importState && isLastChild ? View.VISIBLE : View.GONE); - int checkBoxColor = itemSelected ? activeColorRes : secondaryColorRes; - CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); - - checkBox.setChecked(itemSelected); - checkBox.setClickable(false); - child.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (data.contains(currentItem)) { - data.remove(currentItem); - } else { - data.add(currentItem); - } - notifyDataSetChanged(); - } - }); - - switch (type) { - case PROFILE: - ApplicationModeBean modeBean = (ApplicationModeBean) currentItem; - String profileName = modeBean.userProfileName; - if (Algorithms.isEmpty(profileName)) { - ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null); - profileName = app.getString(appMode.getNameKeyResource()); - } - title.setText(profileName); - String routingProfile = ""; - String routingProfileValue = modeBean.routingProfile; - if (!routingProfileValue.isEmpty()) { - try { - routingProfile = app.getString(RoutingProfilesResources.valueOf(routingProfileValue.toUpperCase()).getStringRes()); - routingProfile = Algorithms.capitalizeFirstLetterAndLowercase(routingProfile); - } catch (IllegalArgumentException e) { - routingProfile = Algorithms.capitalizeFirstLetterAndLowercase(routingProfileValue); - LOG.error("Error trying to get routing resource for " + routingProfileValue + "\n" + e); - } - } - if (!Algorithms.isEmpty(routingProfile)) { - subText.setText(String.format( - app.getString(R.string.ltr_or_rtl_combine_via_colon), - app.getString(R.string.nav_type_hint), - routingProfile)); - subText.setVisibility(View.VISIBLE); - } - int profileIconRes = AndroidUtils.getDrawableId(app, modeBean.iconName); - ProfileIconColors iconColor = modeBean.iconColor; - icon.setImageDrawable(uiUtilities.getIcon(profileIconRes, iconColor.getColor(nightMode))); - break; - case QUICK_ACTIONS: - title.setText(((QuickAction) currentItem).getName(app.getApplicationContext())); - setupIcon(icon, ((QuickAction) currentItem).getIconRes(), itemSelected); - break; - case POI_TYPES: - title.setText(((PoiUIFilter) currentItem).getName()); - int iconRes = RenderingIcons.getBigIconResourceId(((PoiUIFilter) currentItem).getIconId()); - setupIcon(icon, iconRes != 0 ? iconRes : R.drawable.ic_action_user, itemSelected); - break; - case MAP_SOURCES: - title.setText(((ITileSource) currentItem).getName()); - setupIcon(icon, R.drawable.ic_map, itemSelected); - break; - case CUSTOM_RENDER_STYLE: - String renderName = ((File) currentItem).getName(); - renderName = renderName.replace('_', ' ').replaceAll(IndexConstants.RENDERER_INDEX_EXT, ""); - title.setText(renderName); - setupIcon(icon, R.drawable.ic_action_map_style, itemSelected); - break; - case CUSTOM_ROUTING: - String routingName = ((File) currentItem).getName(); - routingName = routingName.replace('_', ' ').replaceAll(".xml", ""); - title.setText(routingName); - setupIcon(icon, R.drawable.ic_action_route_distance, itemSelected); - break; - case AVOID_ROADS: - AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) currentItem; - title.setText(avoidRoadInfo.name); - setupIcon(icon, R.drawable.ic_action_alert, itemSelected); - break; - case MULTIMEDIA_NOTES: - File file = (File) currentItem; - title.setText(file.getName()); - int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file); - if (iconId == -1) { - iconId = R.drawable.ic_action_photo_dark; - } - setupIcon(icon, iconId, itemSelected); - break; - case TRACKS: - String fileName = ((File) currentItem).getName(); - title.setText(GpxUiHelper.getGpxTitle(fileName)); - setupIcon(icon, R.drawable.ic_action_route_distance, itemSelected); - break; - case GLOBAL: - String name = ((GlobalSettingsItem) currentItem).getPublicName(app); - title.setText(name); - setupIcon(icon, R.drawable.ic_action_settings, itemSelected); - break; - case OSM_NOTES: - title.setText(((OsmNotesPoint) currentItem).getText()); - setupIcon(icon, R.drawable.ic_action_osm_note_add, itemSelected); - break; - case OSM_EDITS: - title.setText(OsmEditingPlugin.getTitle((OpenstreetmapPoint) currentItem, app)); - setupIcon(icon, R.drawable.ic_action_info_dark, itemSelected); - break; - case OFFLINE_MAPS: - long size; - if (currentItem instanceof FileSettingsItem) { - FileSettingsItem currentFileItem = (FileSettingsItem) currentItem; - file = currentFileItem.getFile(); - size = currentFileItem.getSize(); - } else { - file = (File) currentItem; - size = file.length(); - } - title.setText(FileNameTranslationHelper.getFileNameWithRegion(app, file.getName())); - FileSubtype subtype = FileSubtype.getSubtypeByPath(app, file.getPath()); - setupIcon(icon, subtype.getIconId(), itemSelected); - subText.setText(AndroidUtils.formatSize(app, size)); - subText.setVisibility(View.VISIBLE); - break; - case FAVORITES: - FavoriteGroup favoriteGroup = (FavoriteGroup) currentItem; - title.setText(favoriteGroup.getDisplayName(app)); - setupIcon(icon, R.drawable.ic_action_favorite, itemSelected); - break; - case TTS_VOICE: - case VOICE: - file = (File) currentItem; - title.setText(FileNameTranslationHelper.getFileNameWithRegion(app, file.getName())); - setupIcon(icon, R.drawable.ic_action_volume_up, itemSelected); - break; - case ACTIVE_MARKERS: - title.setText(R.string.map_markers); - setupIcon(icon, R.drawable.ic_action_flag, itemSelected); - break; - case HISTORY_MARKERS: - title.setText(R.string.markers_history); - setupIcon(icon, R.drawable.ic_action_flag, itemSelected); - break; - case SEARCH_HISTORY: - HistoryEntry historyEntry = (HistoryEntry) currentItem; - title.setText(historyEntry.getName().getName()); - break; - default: - return child; - } - return child; - } - - @Override - public int getGroupCount() { - return itemsTypes.size(); - } - - @Override - public int getChildrenCount(int i) { - return itemsMap.get(itemsTypes.get(i)).size(); - } - - @Override - public Object getGroup(int i) { - return itemsMap.get(itemsTypes.get(i)); - } - - @Override - public Object getChild(int groupPosition, int childPosition) { - return itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); - } - - @Override - public long getGroupId(int i) { - return i; - } - - @Override - public long getChildId(int groupPosition, int childPosition) { - return groupPosition * 10000 + childPosition; - } - - @Override - public boolean hasStableIds() { - return false; - } - - @Override - public boolean isChildSelectable(int i, int i1) { - return true; - } - - private String getSelectedItemsAmount(List listItems, ExportSettingsType type) { - int amount = 0; - long amountSize = 0; - for (Object item : listItems) { - if (data.contains(item)) { - amount++; - if (type == OFFLINE_MAPS) { - if (item instanceof FileSettingsItem) { - amountSize += ((FileSettingsItem) item).getSize(); - } else { - amountSize += ((File) item).length(); - } - } - } - } - String itemsOf = app.getString(R.string.n_items_of_z, String.valueOf(amount), String.valueOf(listItems.size())); - return amountSize == 0 ? itemsOf : app.getString(R.string.ltr_or_rtl_combine_via_bold_point, itemsOf, - AndroidUtils.formatSize(app, amountSize)); - } - - private int getGroupTitle(ExportSettingsType type) { - switch (type) { - case PROFILE: - return R.string.shared_string_profiles; - case QUICK_ACTIONS: - return R.string.configure_screen_quick_action; - case POI_TYPES: - return R.string.poi_dialog_poi_type; - case MAP_SOURCES: - return R.string.quick_action_map_source_title; - case CUSTOM_RENDER_STYLE: - return R.string.shared_string_rendering_style; - case CUSTOM_ROUTING: - return R.string.shared_string_routing; - case AVOID_ROADS: - return R.string.avoid_road; - case TRACKS: - return R.string.shared_string_tracks; - case MULTIMEDIA_NOTES: - return R.string.audionotes_plugin_name; - case GLOBAL: - return R.string.general_settings_2; - case OSM_NOTES: - return R.string.osm_notes; - case OSM_EDITS: - return R.string.osm_edits; - case OFFLINE_MAPS: - return R.string.shared_string_maps; - case FAVORITES: - return R.string.shared_string_favorites; - case TTS_VOICE: - return R.string.local_indexes_cat_tts; - case VOICE: - return R.string.local_indexes_cat_voice; - case ACTIVE_MARKERS: - return R.string.map_markers; - case HISTORY_MARKERS: - return R.string.markers_history; - case SEARCH_HISTORY: - return R.string.shared_string_search_history; - default: - return R.string.access_empty_list; - } - } - - private void setupIcon(ImageView icon, int iconRes, boolean itemSelected) { - if (itemSelected) { - icon.setImageDrawable(uiUtilities.getIcon(iconRes, activeColorRes)); - } else { - icon.setImageDrawable(uiUtilities.getIcon(iconRes, nightMode)); - } - } - - public void updateSettingsList(Map> itemsMap) { - this.itemsMap = itemsMap; - this.itemsTypes = new ArrayList<>(itemsMap.keySet()); - Collections.sort(itemsTypes); - notifyDataSetChanged(); - } - - public void clearSettingsList() { - this.itemsMap.clear(); - this.itemsTypes.clear(); - notifyDataSetChanged(); - } - - public void selectAll(boolean selectAll) { - data.clear(); - if (selectAll) { - for (List values : itemsMap.values()) { - data.addAll(values); - } - } - notifyDataSetChanged(); - } - - List getData() { - return this.data; - } -} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java new file mode 100644 index 0000000000..0a310e5c16 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java @@ -0,0 +1,468 @@ +package net.osmand.plus.settings.fragments; + +import android.content.res.ColorStateList; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.core.widget.CompoundButtonCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import net.osmand.AndroidUtils; +import net.osmand.GPXUtilities.GPXTrackAnalysis; +import net.osmand.IndexConstants; +import net.osmand.PlatformUtil; +import net.osmand.map.ITileSource; +import net.osmand.map.TileSourceManager.TileSourceTemplate; +import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; +import net.osmand.plus.GPXDatabase.GpxDataItem; +import net.osmand.plus.GpxDbHelper.GpxDataItemCallback; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.SQLiteTileSource; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.audionotes.AudioVideoNotesPlugin; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Builder; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem; +import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; +import net.osmand.plus.helpers.FileNameTranslationHelper; +import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry; +import net.osmand.plus.mapmarkers.MapMarkersGroup; +import net.osmand.plus.osmedit.OpenstreetmapPoint; +import net.osmand.plus.osmedit.OsmEditingPlugin; +import net.osmand.plus.osmedit.OsmNotesPoint; +import net.osmand.plus.poi.PoiUIFilter; +import net.osmand.plus.profiles.ProfileIconColors; +import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources; +import net.osmand.plus.quickaction.QuickAction; +import net.osmand.plus.render.RenderingIcons; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; +import net.osmand.plus.settings.backend.ExportSettingsType; +import net.osmand.plus.settings.backend.backup.FileSettingsItem; +import net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype; +import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; +import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener; +import net.osmand.util.Algorithms; +import net.osmand.view.ThreeStateCheckbox; + +import org.apache.commons.logging.Log; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import static net.osmand.view.ThreeStateCheckbox.State.CHECKED; +import static net.osmand.view.ThreeStateCheckbox.State.MISC; +import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED; + +public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { + + public static final String TAG = ExportItemsBottomSheet.class.getSimpleName(); + private static final Log LOG = PlatformUtil.getLog(ExportItemsBottomSheet.class); + + private static final String SETTINGS_TYPE_KEY = "settings_type_key"; + private static final String EXPORT_MODE_KEY = "export_mode_key"; + + private OsmandApplication app; + private UiUtilities uiUtilities; + + private ExportSettingsType type; + private final List allItems = new ArrayList<>(); + private final List selectedItems = new ArrayList<>(); + + private TextView selectedSize; + private ThreeStateCheckbox checkBox; + + private int activeColorRes; + private int secondaryColorRes; + private boolean exportMode; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null) { + exportMode = savedInstanceState.getBoolean(EXPORT_MODE_KEY); + type = ExportSettingsType.valueOf(savedInstanceState.getString(SETTINGS_TYPE_KEY)); + } + Fragment target = getTargetFragment(); + if (target instanceof BaseSettingsListFragment) { + BaseSettingsListFragment fragment = (BaseSettingsListFragment) target; + List items = fragment.getItemsForType(type); + if (items != null) { + allItems.addAll(items); + } + List selectedItemsForType = fragment.getSelectedItemsForType(type); + if (selectedItemsForType != null) { + selectedItems.addAll(selectedItemsForType); + } + } + } + + @Override + public void createMenuItems(Bundle savedInstanceState) { + app = requiredMyApplication(); + uiUtilities = app.getUIUtilities(); + activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; + secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light; + + items.add(createTitleItem()); + items.add(new SimpleDividerItem(app)); + + for (Object object : allItems) { + final BottomSheetItemWithCompoundButton[] item = new BottomSheetItemWithCompoundButton[1]; + Builder builder = (BottomSheetItemWithCompoundButton.Builder) new Builder() + .setChecked(selectedItems.contains(object)) + .setButtonTintList(AndroidUtils.createCheckedColorStateList(app, secondaryColorRes, activeColorRes)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean checked = !item[0].isChecked(); + item[0].setChecked(checked); + if (checked) { + selectedItems.add(item[0].getTag()); + } else { + selectedItems.remove(item[0].getTag()); + } + updateTitleView(); + } + }) + .setTag(object); + setupBottomSheetItem(builder, object); + item[0] = builder.create(); + items.add(item[0]); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(EXPORT_MODE_KEY, exportMode); + outState.putString(SETTINGS_TYPE_KEY, type.name()); + } + + private BaseBottomSheetItem createTitleItem() { + LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode); + View view = themedInflater.inflate(R.layout.settings_group_title, null); + + checkBox = view.findViewById(R.id.check_box); + selectedSize = view.findViewById(R.id.selected_size); + TextView textView = view.findViewById(R.id.title); + textView.setText(type.getTitleId()); + view.findViewById(R.id.select_all_button).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + checkBox.performClick(); + boolean checked = checkBox.getState() == CHECKED; + if (checked) { + selectedItems.addAll(allItems); + } else { + selectedItems.clear(); + } + updateTitleView(); + updateItems(checked); + } + }); + setupDescription(view); + updateTitleView(); + + return new SimpleBottomSheetItem.Builder().setCustomView(view).create(); + } + + private void updateTitleView() { + if (Algorithms.isEmpty(selectedItems)) { + checkBox.setState(UNCHECKED); + } else { + checkBox.setState(selectedItems.containsAll(allItems) ? CHECKED : MISC); + } + int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; + CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); + + String description; + if (type == ExportSettingsType.OFFLINE_MAPS && !selectedItems.isEmpty()) { + String size = AndroidUtils.formatSize(app, calculateSelectedItemsSize()); + String selected = getString(R.string.ltr_or_rtl_combine_via_slash, selectedItems.size(), allItems.size()); + description = getString(R.string.ltr_or_rtl_combine_via_comma, selected, size); + } else { + description = getString(R.string.ltr_or_rtl_combine_via_slash, selectedItems.size(), allItems.size()); + } + selectedSize.setText(description); + } + + private long calculateSelectedItemsSize() { + long itemsSize = 0; + for (int i = 0; i < allItems.size(); i++) { + Object object = allItems.get(i); + if (selectedItems.contains(object)) { + if (object instanceof FileSettingsItem) { + itemsSize += ((FileSettingsItem) object).getSize(); + } else if (object instanceof File) { + itemsSize += ((File) object).length(); + } + } + } + return itemsSize; + } + + private void updateItems(boolean checked) { + for (BaseBottomSheetItem item : items) { + if (item instanceof BottomSheetItemWithCompoundButton) { + ((BottomSheetItemWithCompoundButton) item).setChecked(checked); + } + } + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_cancel; + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_apply; + } + + @Override + protected void onRightBottomButtonClick() { + Fragment target = getTargetFragment(); + if (target instanceof OnItemSelectedListener) { + OnItemSelectedListener listener = (OnItemSelectedListener) target; + listener.onItemsSelected(type, selectedItems); + } + dismiss(); + } + + public static void showInstance(@NonNull FragmentManager fm, @NonNull ExportSettingsType type, + @NonNull BaseSettingsListFragment target, boolean exportMode) { + try { + if (!fm.isStateSaved() && fm.findFragmentByTag(TAG) == null) { + ExportItemsBottomSheet fragment = new ExportItemsBottomSheet(); + fragment.type = type; + fragment.exportMode = exportMode; + fragment.setTargetFragment(target, 0); + fragment.show(fm, TAG); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } + + private String setupDescription(View view) { + TextView description = view.findViewById(R.id.description); + if (type == ExportSettingsType.FAVORITES) { + description.setText(R.string.select_groups_for_import); + } else { + description.setText(R.string.select_items_for_import); + } + return null; + } + + private void setupBottomSheetItem(Builder builder, Object object) { + if (object instanceof ApplicationModeBean) { + ApplicationModeBean modeBean = (ApplicationModeBean) object; + String profileName = modeBean.userProfileName; + if (Algorithms.isEmpty(profileName)) { + ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null); + profileName = getString(appMode.getNameKeyResource()); + } + builder.setTitle(profileName); + + String routingProfile = ""; + String routingProfileValue = modeBean.routingProfile; + if (!routingProfileValue.isEmpty()) { + try { + routingProfile = getString(RoutingProfilesResources.valueOf(routingProfileValue.toUpperCase()).getStringRes()); + routingProfile = Algorithms.capitalizeFirstLetterAndLowercase(routingProfile); + } catch (IllegalArgumentException e) { + routingProfile = Algorithms.capitalizeFirstLetterAndLowercase(routingProfileValue); + LOG.error("Error trying to get routing resource for " + routingProfileValue + "\n" + e); + } + } + if (!Algorithms.isEmpty(routingProfile)) { + builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_colon, getString(R.string.nav_type_hint), routingProfile)); + } else { + builder.setDescription(getString(R.string.profile_type_base_string)); + } + int profileIconRes = AndroidUtils.getDrawableId(app, modeBean.iconName); + ProfileIconColors iconColor = modeBean.iconColor; + builder.setIcon(uiUtilities.getIcon(profileIconRes, iconColor.getColor(nightMode))); + } else if (object instanceof QuickAction) { + QuickAction quickAction = (QuickAction) object; + builder.setTitle(quickAction.getName(app)); + builder.setIcon(uiUtilities.getIcon(quickAction.getIconRes(), activeColorRes)); + } else if (object instanceof PoiUIFilter) { + PoiUIFilter poiUIFilter = (PoiUIFilter) object; + builder.setTitle(poiUIFilter.getName()); + int iconRes = RenderingIcons.getBigIconResourceId(poiUIFilter.getIconId()); + builder.setIcon(uiUtilities.getIcon(iconRes != 0 ? iconRes : R.drawable.ic_action_user, activeColorRes)); + } else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) { + ITileSource tileSource = (ITileSource) object; + builder.setTitle(tileSource.getName()); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_map, activeColorRes)); + } else if (object instanceof File) { + File file = (File) object; + setupBottomSheetItemForFile(builder, file, file.lastModified(), file.length()); + } else if (object instanceof FileSettingsItem) { + FileSettingsItem item = (FileSettingsItem) object; + setupBottomSheetItemForFile(builder, item.getFile(), item.getLastModified(), item.getSize()); + } else if (object instanceof AvoidRoadInfo) { + AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) object; + builder.setTitle(avoidRoadInfo.name); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_alert, activeColorRes)); + } else if (object instanceof OsmNotesPoint) { + OsmNotesPoint osmNotesPoint = (OsmNotesPoint) object; + builder.setTitle(osmNotesPoint.getText()); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_osm_note_add, activeColorRes)); + } else if (object instanceof OpenstreetmapPoint) { + OpenstreetmapPoint openstreetmapPoint = (OpenstreetmapPoint) object; + builder.setTitle(OsmEditingPlugin.getTitle(openstreetmapPoint, app)); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_info_dark, activeColorRes)); + } else if (object instanceof FavoriteGroup) { + FavoriteGroup group = (FavoriteGroup) object; + builder.setTitle(group.getDisplayName(app)); + int color = group.getColor() == 0 ? ContextCompat.getColor(app, R.color.color_favorite) : group.getColor(); + builder.setIcon(uiUtilities.getPaintedIcon(R.drawable.ic_action_folder, color)); + int points = group.getPoints().size(); + String itemsDescr = getString(R.string.shared_string_gpx_points); + builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_colon, itemsDescr, points)); + } else if (object instanceof GlobalSettingsItem) { + GlobalSettingsItem globalSettingsItem = (GlobalSettingsItem) object; + builder.setTitle(globalSettingsItem.getPublicName(app)); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_settings, activeColorRes)); + } else if (object instanceof MapMarkersGroup) { + MapMarkersGroup markersGroup = (MapMarkersGroup) object; + if (ExportSettingsType.ACTIVE_MARKERS.name().equals(markersGroup.getId())) { + builder.setTitle(getString(R.string.map_markers)); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_flag, activeColorRes)); + } else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) { + builder.setTitle(getString(R.string.markers_history)); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_history, activeColorRes)); + } + int selectedMarkers = markersGroup.getMarkers().size(); + String itemsDescr = getString(R.string.shared_string_items); + builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_colon, itemsDescr, selectedMarkers)); + } else if (object instanceof HistoryEntry) { + HistoryEntry historyEntry = (HistoryEntry) object; + builder.setTitle(historyEntry.getName().getName()); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_history, activeColorRes)); + } + } + + private void setupBottomSheetItemForFile(Builder builder, File file, long lastModified, long size) { + FileSubtype fileSubtype = FileSubtype.getSubtypeByPath(app, file.getPath()); + builder.setTitle(file.getName()); + if (file.getAbsolutePath().contains(IndexConstants.RENDERERS_DIR)) { + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_map_style, activeColorRes)); + } else if (file.getAbsolutePath().contains(IndexConstants.ROUTING_PROFILES_DIR)) { + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); + } else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) { + builder.setTitle(GpxUiHelper.getGpxTitle(file.getName())); + builder.setTag(file); + builder.setDescription(getTrackDescr(file, lastModified, size)); + builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); + } else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) { + int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file); + if (iconId == -1) { + iconId = R.drawable.ic_action_photo_dark; + } + builder.setIcon(uiUtilities.getIcon(iconId, activeColorRes)); + } else if (fileSubtype.isMap() + || fileSubtype == FileSettingsItem.FileSubtype.TTS_VOICE + || fileSubtype == FileSettingsItem.FileSubtype.VOICE) { + builder.setTitle(FileNameTranslationHelper.getFileNameWithRegion(app, file.getName())); + builder.setIcon(uiUtilities.getIcon(fileSubtype.getIconId(), activeColorRes)); + + if (fileSubtype.isMap()) { + String mapDescription = getMapDescription(file); + String formattedSize = AndroidUtils.formatSize(app, size); + if (mapDescription != null) { + builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_star, mapDescription, formattedSize)); + } else { + builder.setDescription(formattedSize); + } + } + } + } + + private final GpxDataItemCallback gpxDataItemCallback = new GpxDataItemCallback() { + @Override + public boolean isCancelled() { + return false; + } + + @Override + public void onGpxDataItemReady(GpxDataItem item) { + for (BaseBottomSheetItem bottomSheetItem : items) { + if (Algorithms.objectEquals(item.getFile(), bottomSheetItem.getTag())) { + ((BottomSheetItemWithDescription) bottomSheetItem).setDescription(getTrackDescrForDataItem(item)); + break; + } + } + } + }; + + private String getTrackDescr(@NonNull File file, long lastModified, long size) { + String folder = ""; + File parent = file.getParentFile(); + if (parent != null) { + folder = Algorithms.capitalizeFirstLetter(parent.getName()); + } + if (exportMode) { + GpxDataItem dataItem = getDataItem(file, gpxDataItemCallback); + if (dataItem != null) { + return getTrackDescrForDataItem(dataItem); + } + } else { + String date = OsmAndFormatter.getFormattedDate(app, lastModified); + String formattedSize = AndroidUtils.formatSize(app, size); + String descr = getString(R.string.ltr_or_rtl_combine_via_bold_point, folder, date); + return getString(R.string.ltr_or_rtl_combine_via_comma, descr, formattedSize); + } + return null; + } + + private String getTrackDescrForDataItem(@NonNull GpxDataItem dataItem) { + GPXTrackAnalysis analysis = dataItem.getAnalysis(); + if (analysis != null) { + File parent = dataItem.getFile().getParentFile(); + String folder = Algorithms.capitalizeFirstLetter(parent.getName()); + String dist = OsmAndFormatter.getFormattedDistance(analysis.totalDistance, app); + String points = analysis.wptPoints + " " + getString(R.string.shared_string_gpx_points).toLowerCase(); + String descr = getString(R.string.ltr_or_rtl_combine_via_bold_point, folder, dist); + return getString(R.string.ltr_or_rtl_combine_via_comma, descr, points); + } + return null; + } + + private GpxDataItem getDataItem(File file, @Nullable GpxDataItemCallback callback) { + return app.getGpxDbHelper().getItem(file, callback); + } + + private String getMapDescription(File file) { + if (file.isDirectory() || file.getName().endsWith(IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT)) { + return getString(R.string.online_map); + } else if (file.getName().endsWith(IndexConstants.BINARY_ROAD_MAP_INDEX_EXT)) { + return getString(R.string.download_roads_only_item); + } else if (file.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) { + return getString(R.string.download_wikipedia_maps); + } else if (file.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) { + return getString(R.string.download_srtm_maps); + } else if (file.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) { + return getString(R.string.download_regular_maps); + } + return null; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java index 65cd471216..1eec036171 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java @@ -18,9 +18,11 @@ import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.FontCache; +import net.osmand.plus.mapmarkers.MapMarkersGroup; import net.osmand.plus.settings.backend.ExportSettingsCategory; import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.FileSettingsItem; +import net.osmand.util.Algorithms; import net.osmand.view.ThreeStateCheckbox; import org.apache.commons.logging.Log; @@ -28,8 +30,6 @@ import org.apache.commons.logging.Log; import java.io.File; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -39,14 +39,14 @@ import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED; public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { - private static final Log LOG = PlatformUtil.getLog(ExportImportSettingsAdapter.class.getName()); + private static final Log LOG = PlatformUtil.getLog(ExportSettingsAdapter.class.getName()); private final OsmandApplication app; private final UiUtilities uiUtilities; - private List itemsTypes = new ArrayList<>(); - private Map> selectedItemsMap = new HashMap<>(); - private Map> itemsMap = new LinkedHashMap<>(); + private List itemsTypes; + private Map> selectedItemsMap; + private Map itemsMap; private final OnItemSelectedListener listener; @@ -55,6 +55,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { private final boolean nightMode; private final int activeColorRes; private final int secondaryColorRes; + private final int groupViewHeight; + private final int childViewHeight; + private final int listBottomPadding; ExportSettingsAdapter(OsmandApplication app, OnItemSelectedListener listener, boolean nightMode) { this.app = app; @@ -64,6 +67,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { themedInflater = UiUtilities.getInflater(app, nightMode); activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light; + groupViewHeight = app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_group_height); + childViewHeight = app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_large_height); + listBottomPadding = app.getResources().getDimensionPixelSize(R.dimen.fab_recycler_view_padding_bottom); } @Override @@ -71,9 +77,10 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { View group = convertView; if (group == null) { group = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); + group.findViewById(R.id.item_container).setMinimumHeight(groupViewHeight); } final ExportSettingsCategory category = itemsTypes.get(groupPosition); - final List items = itemsMap.get(category); + final SettingsCategoryItems items = itemsMap.get(category); String title = app.getString(category.getTitleId()); TextView titleTv = group.findViewById(R.id.title_tv); @@ -83,9 +90,8 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { subTextTv.setText(getCategoryDescr(category)); int selectedTypes = 0; - for (int i = 0; i < items.size(); i++) { - ExportDataObject object = items.get(i); - if (selectedItemsMap.containsKey(object.getType())) { + for (ExportSettingsType type : items.getTypes()) { + if (!Algorithms.isEmpty(selectedItemsMap.get(type))) { selectedTypes++; } } @@ -93,7 +99,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { if (selectedTypes == 0) { checkBox.setState(UNCHECKED); } else { - checkBox.setState(selectedTypes == items.size() ? CHECKED : MISC); + checkBox.setState(selectedTypes == items.getTypes().size() ? CHECKED : MISC); } int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); @@ -103,17 +109,6 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { public void onClick(View view) { checkBox.performClick(); boolean selected = checkBox.getState() == CHECKED; - if (selected) { - for (ExportDataObject object : items) { - if (!selectedItemsMap.containsKey(object.getType())) { - selectedItemsMap.put(object.getType(), object.getItems()); - } - } - } else { - for (ExportDataObject object : items) { - selectedItemsMap.remove(object.getType()); - } - } if (listener != null) { listener.onCategorySelected(category, selected); } @@ -121,6 +116,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { } }); + boolean addPadding = !isExpanded && groupPosition == getGroupCount() - 1; + group.setPadding(0, 0, 0, addPadding ? listBottomPadding : 0); + adjustIndicator(app, groupPosition, isExpanded, group, nightMode); AndroidUiHelper.updateVisibility(group.findViewById(R.id.divider), isExpanded); AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_top_divider), true); @@ -135,27 +133,31 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { View child = convertView; if (child == null) { child = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); + child.findViewById(R.id.item_container).setMinimumHeight(childViewHeight); } - final ExportDataObject currentItem = itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); - List selectedItems = selectedItemsMap.get(currentItem.getType()); + final ExportSettingsCategory category = itemsTypes.get(groupPosition); + final SettingsCategoryItems categoryItems = itemsMap.get(category); + final ExportSettingsType type = categoryItems.getTypes().get(childPosition); + final List items = categoryItems.getItemsForType(type); + List selectedItems = selectedItemsMap.get(type); TextView titleTv = child.findViewById(R.id.title_tv); - titleTv.setText(currentItem.getType().getTitleId()); + titleTv.setText(type.getTitleId()); TextView subTextTv = child.findViewById(R.id.sub_text_tv); - subTextTv.setText(getSelectedTypeDescr(currentItem)); + subTextTv.setText(getSelectedTypeDescr(type, items)); ImageView icon = child.findViewById(R.id.explist_indicator); - setupIcon(icon, currentItem.getType().getIconRes(), selectedItems != null); + setupIcon(icon, type.getIconRes(), !Algorithms.isEmpty(selectedItems)); final ThreeStateCheckbox checkBox = child.findViewById(R.id.check_box); if (selectedItems == null) { checkBox.setState(UNCHECKED); - } else if (selectedItems.containsAll(currentItem.getItems())) { + } else if (selectedItems.containsAll(items)) { checkBox.setState(CHECKED); } else { boolean contains = false; - for (Object object : currentItem.getItems()) { + for (Object object : items) { if (selectedItems.contains(object)) { contains = true; break; @@ -163,7 +165,14 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { } checkBox.setState(contains ? MISC : UNCHECKED); } - + child.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onTypeClicked(type); + } + } + }); int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); child.findViewById(R.id.check_box_container).setOnClickListener(new View.OnClickListener() { @@ -171,18 +180,14 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { public void onClick(View view) { checkBox.performClick(); boolean selected = checkBox.getState() == CHECKED; - if (selected) { - selectedItemsMap.put(currentItem.getType(), currentItem.getItems()); - } else { - selectedItemsMap.remove(currentItem.getType()); - } if (listener != null) { - listener.onTypeSelected(currentItem.getType(), selected); + listener.onItemsSelected(type, selected ? items : new ArrayList<>()); } notifyDataSetChanged(); } }); - + boolean addPadding = isLastChild && groupPosition == getGroupCount() - 1; + child.setPadding(0, 0, 0, addPadding ? listBottomPadding : 0); AndroidUiHelper.updateVisibility(child.findViewById(R.id.card_bottom_divider), isLastChild); return child; @@ -195,7 +200,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { @Override public int getChildrenCount(int i) { - return itemsMap.get(itemsTypes.get(i)).size(); + return itemsMap.get(itemsTypes.get(i)).getTypes().size(); } @Override @@ -205,7 +210,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { @Override public Object getChild(int groupPosition, int childPosition) { - return itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); + SettingsCategoryItems categoryItems = itemsMap.get(itemsTypes.get(groupPosition)); + ExportSettingsType type = categoryItems.getTypes().get(groupPosition); + return categoryItems.getItemsForType(type).get(childPosition); } @Override @@ -237,9 +244,11 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { } } - public void updateSettingsList(Map> itemsMap) { + public void updateSettingsItems(Map itemsMap, + Map> selectedItemsMap) { this.itemsMap = itemsMap; this.itemsTypes = new ArrayList<>(itemsMap.keySet()); + this.selectedItemsMap = selectedItemsMap; Collections.sort(itemsTypes); notifyDataSetChanged(); } @@ -247,13 +256,10 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { public void clearSettingsList() { this.itemsMap.clear(); this.itemsTypes.clear(); + this.selectedItemsMap.clear(); notifyDataSetChanged(); } - public boolean hasSelectedData() { - return !selectedItemsMap.isEmpty(); - } - public List getData() { List selectedItems = new ArrayList<>(); for (List items : selectedItemsMap.values()) { @@ -265,21 +271,20 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { private String getCategoryDescr(ExportSettingsCategory category) { long itemsSize = 0; int selectedTypes = 0; - List items = itemsMap.get(category); - for (int i = 0; i < items.size(); i++) { - ExportDataObject object = items.get(i); - if (selectedItemsMap.containsKey(object.getType())) { + SettingsCategoryItems items = itemsMap.get(category); + for (ExportSettingsType type : items.getTypes()) { + if (!Algorithms.isEmpty(selectedItemsMap.get(type))) { selectedTypes++; - itemsSize += calculateItemsSize(object.getItems()); + itemsSize += calculateItemsSize(items.getItemsForType(type)); } } String description; if (selectedTypes == 0) { description = app.getString(R.string.shared_string_none); - } else if (selectedTypes == items.size()) { + } else if (selectedTypes == items.getTypes().size()) { description = app.getString(R.string.shared_string_all); } else { - description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.size())); + description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.getTypes().size())); } String formattedSize = AndroidUtils.formatSize(app, itemsSize); return itemsSize == 0 ? description : app.getString(R.string.ltr_or_rtl_combine_via_comma, description, formattedSize); @@ -297,12 +302,11 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { return itemsSize; } - private String getSelectedTypeDescr(ExportDataObject dataObject) { + private String getSelectedTypeDescr(ExportSettingsType type, List items) { long itemsSize = 0; int selectedTypes = 0; - List items = dataObject.getItems(); - List selectedItems = selectedItemsMap.get(dataObject.getType()); + List selectedItems = selectedItemsMap.get(type); if (selectedItems != null) { for (int i = 0; i < items.size(); i++) { Object object = items.get(i); @@ -312,6 +316,10 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { itemsSize += ((FileSettingsItem) object).getSize(); } else if (object instanceof File) { itemsSize += ((File) object).length(); + } else if (object instanceof MapMarkersGroup) { + int selectedMarkers = ((MapMarkersGroup) object).getMarkers().size(); + String itemsDescr = app.getString(R.string.shared_string_items); + return app.getString(R.string.ltr_or_rtl_combine_via_colon, itemsDescr, selectedMarkers); } } } @@ -333,9 +341,11 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { interface OnItemSelectedListener { + void onItemsSelected(ExportSettingsType type, List selectedItems); + void onCategorySelected(ExportSettingsCategory type, boolean selected); - void onTypeSelected(ExportSettingsType type, boolean selected); + void onTypeClicked(ExportSettingsType type); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java index ce9d1f414e..af954db7c5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java @@ -4,24 +4,15 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.os.Build; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.ExpandableListView; -import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; -import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; -import androidx.core.view.ViewCompat; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; @@ -31,20 +22,11 @@ import net.osmand.AndroidUtils; import net.osmand.FileUtils; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; -import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.UiUtilities; -import net.osmand.plus.UiUtilities.DialogButtonType; -import net.osmand.plus.base.BaseOsmAndFragment; -import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.settings.backend.ApplicationMode; -import net.osmand.plus.settings.backend.ExportSettingsCategory; -import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener; import net.osmand.plus.settings.backend.backup.SettingsItem; -import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener; -import net.osmand.plus.widgets.TextViewEx; import org.apache.commons.logging.Log; @@ -53,11 +35,10 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; -import java.util.Map; import static net.osmand.plus.settings.fragments.BaseSettingsFragment.APP_MODE_KEY; -public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItemSelectedListener { +public class ExportSettingsFragment extends BaseSettingsListFragment { public static final String TAG = ImportSettingsFragment.class.getSimpleName(); public static final Log LOG = PlatformUtil.getLog(ImportSettingsFragment.class.getSimpleName()); @@ -73,43 +54,19 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yy", Locale.US); - private OsmandApplication app; - private Map> dataList; - private ProgressDialog progress; private ApplicationMode appMode; private SettingsExportListener exportListener; - private View continueBtn; - private View headerShadow; - private View headerDivider; - private View itemsSizeContainer; - private View availableSpaceContainer; - private TextViewEx selectedItemsSize; - private TextViewEx availableSpaceDescr; - private LinearLayout buttonsContainer; - private ExpandableListView expandableList; - private ExportSettingsAdapter adapter; - private int progressMax; private int progressValue; - private long exportStartTime; - - private boolean nightMode; private boolean globalExport; private boolean exportingStarted; - @Override - public int getStatusBarColorId() { - return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light; - } - @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - app = requireMyApplication(); - nightMode = !app.getSettings().isLightContent(); if (savedInstanceState != null) { appMode = ApplicationMode.valueOfStringKey(savedInstanceState.getString(APP_MODE_KEY), null); globalExport = savedInstanceState.getBoolean(GLOBAL_EXPORT_KEY); @@ -118,77 +75,26 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem progressMax = savedInstanceState.getInt(PROGRESS_MAX_KEY); progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY); } + exportMode = true; dataList = app.getSettingsHelper().getAdditionalData(globalExport); - - requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { - @Override - public void handleOnBackPressed() { - showExitDialog(); - } - }); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - LayoutInflater themedInflater = UiUtilities.getInflater(app, nightMode); - View root = themedInflater.inflate(R.layout.fragment_import, container, false); - AndroidUtils.addStatusBarPadding21v(app, root); + View view = super.onCreateView(inflater, container, savedInstanceState); - selectedItemsSize = root.findViewById(R.id.file_size); - itemsSizeContainer = root.findViewById(R.id.file_size_container); - expandableList = root.findViewById(R.id.list); - buttonsContainer = root.findViewById(R.id.buttons_container); - - Toolbar toolbar = root.findViewById(R.id.toolbar); - setupToolbar(toolbar); - ViewCompat.setNestedScrollingEnabled(expandableList, true); - - View header = themedInflater.inflate(R.layout.list_item_description_header, null); - headerDivider = header.findViewById(R.id.divider); - headerShadow = header.findViewById(R.id.card_bottom_divider); - expandableList.addHeaderView(header); - - availableSpaceContainer = themedInflater.inflate(R.layout.enough_space_warning_card, null); - availableSpaceDescr = availableSpaceContainer.findViewById(R.id.warning_descr); - - continueBtn = root.findViewById(R.id.continue_button); - UiUtilities.setupDialogButton(nightMode, continueBtn, DialogButtonType.PRIMARY, getString(R.string.shared_string_continue)); - continueBtn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - prepareFile(); - } - }); - - ViewTreeObserver treeObserver = buttonsContainer.getViewTreeObserver(); - treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (buttonsContainer != null) { - ViewTreeObserver vts = buttonsContainer.getViewTreeObserver(); - int height = buttonsContainer.getMeasuredHeight(); - expandableList.setPadding(0, 0, 0, height); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - vts.removeOnGlobalLayoutListener(this); - } else { - vts.removeGlobalOnLayoutListener(this); - } - } - } - }); - - adapter = new ExportSettingsAdapter(app, this, nightMode); - adapter.updateSettingsList(dataList); - expandableList.setAdapter(adapter); - - CollapsingToolbarLayout toolbarLayout = root.findViewById(R.id.toolbar_layout); + CollapsingToolbarLayout toolbarLayout = view.findViewById(R.id.toolbar_layout); toolbarLayout.setTitle(getString(R.string.shared_string_export)); TextView description = header.findViewById(R.id.description); description.setText(R.string.select_data_to_export); - updateAvailableSpace(); - return root; + return view; + } + + @Override + protected void onContinueButtonClickAction() { + prepareFile(); } @Override @@ -219,88 +125,6 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem } } - private void dismissFragment() { - FragmentManager fm = getFragmentManager(); - if (fm != null && !fm.isStateSaved()) { - getFragmentManager().popBackStack(EXPORT_SETTINGS_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); - } - } - - public void showExitDialog() { - Context themedContext = UiUtilities.getThemedContext(getActivity(), nightMode); - AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext); - dismissDialog.setTitle(getString(R.string.shared_string_dismiss)); - dismissDialog.setMessage(getString(R.string.exit_without_saving)); - dismissDialog.setNegativeButton(R.string.shared_string_cancel, null); - dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dismissFragment(); - } - }); - dismissDialog.show(); - } - - private void setupToolbar(Toolbar toolbar) { - int color = ContextCompat.getColor(app, nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light); - toolbar.setNavigationIcon(getPaintedContentIcon(R.drawable.ic_action_close, color)); - toolbar.setNavigationContentDescription(R.string.shared_string_close); - toolbar.setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showExitDialog(); - } - }); - } - - private void updateAvailableSpace() { - long calculatedSize = ExportSettingsAdapter.calculateItemsSize(adapter.getData()); - if (calculatedSize != 0) { - selectedItemsSize.setText(AndroidUtils.formatSize(app, calculatedSize)); - - File dir = app.getAppPath("").getParentFile(); - long availableSizeBytes = AndroidUtils.getAvailableSpace(dir); - if (calculatedSize > availableSizeBytes) { - String availableSize = AndroidUtils.formatSize(app, availableSizeBytes); - availableSpaceDescr.setText(getString(R.string.export_not_enough_space_descr, availableSize)); - updateWarningHeaderVisibility(true); - continueBtn.setEnabled(false); - } else { - updateWarningHeaderVisibility(false); - continueBtn.setEnabled(adapter.hasSelectedData()); - } - itemsSizeContainer.setVisibility(View.VISIBLE); - } else { - updateWarningHeaderVisibility(false); - itemsSizeContainer.setVisibility(View.INVISIBLE); - continueBtn.setEnabled(adapter.hasSelectedData()); - } - } - - private void updateWarningHeaderVisibility(boolean visible) { - if (visible) { - if (expandableList.getHeaderViewsCount() < 2) { - expandableList.addHeaderView(availableSpaceContainer); - } - AndroidUiHelper.updateVisibility(headerShadow, false); - AndroidUiHelper.updateVisibility(headerDivider, true); - } else { - expandableList.removeHeaderView(availableSpaceContainer); - AndroidUiHelper.updateVisibility(headerShadow, true); - AndroidUiHelper.updateVisibility(headerDivider, false); - } - } - - @Override - public void onCategorySelected(ExportSettingsCategory type, boolean selected) { - updateAvailableSpace(); - } - - @Override - public void onTypeSelected(ExportSettingsType type, boolean selected) { - updateAvailableSpace(); - } - private void prepareFile() { if (app != null) { exportingStarted = true; @@ -445,7 +269,7 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem fragment.globalExport = globalExport; fragmentManager.beginTransaction(). replace(R.id.fragmentContainer, fragment, TAG) - .addToBackStack(EXPORT_SETTINGS_TAG) + .addToBackStack(SETTINGS_LIST_TAG) .commitAllowingStateLoss(); return true; } catch (RuntimeException e) { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportCompleteFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportCompleteFragment.java index 68087cf71f..8893fb3f97 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportCompleteFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportCompleteFragment.java @@ -40,7 +40,7 @@ import net.osmand.plus.settings.backend.backup.SettingsItem; import java.util.List; import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_SETTINGS_ID; -import static net.osmand.plus.settings.fragments.ImportSettingsFragment.IMPORT_SETTINGS_TAG; +import static net.osmand.plus.settings.fragments.BaseSettingsListFragment.SETTINGS_LIST_TAG; public class ImportCompleteFragment extends BaseOsmAndFragment { public static final String TAG = ImportCompleteFragment.class.getSimpleName(); @@ -58,7 +58,7 @@ public class ImportCompleteFragment extends BaseOsmAndFragment { fragment.setRetainInstance(true); fm.beginTransaction() .replace(R.id.fragmentContainer, fragment, TAG) - .addToBackStack(IMPORT_SETTINGS_TAG) + .addToBackStack(SETTINGS_LIST_TAG) .commitAllowingStateLoss(); } @@ -137,7 +137,7 @@ public class ImportCompleteFragment extends BaseOsmAndFragment { public void dismissFragment() { FragmentManager fm = getFragmentManager(); if (fm != null && !fm.isStateSaved()) { - fm.popBackStack(IMPORT_SETTINGS_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); + fm.popBackStack(SETTINGS_LIST_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); } } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportDuplicatesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportDuplicatesFragment.java index 6d5b74cef7..4d75a27e4d 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportDuplicatesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportDuplicatesFragment.java @@ -33,13 +33,12 @@ import net.osmand.plus.UiUtilities; import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry; -import net.osmand.plus.mapmarkers.MapMarkersGroup; +import net.osmand.plus.mapmarkers.MapMarker; import net.osmand.plus.osmedit.OpenstreetmapPoint; import net.osmand.plus.osmedit.OsmNotesPoint; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.settings.backend.ApplicationMode; -import net.osmand.plus.settings.backend.ExportSettingsType; 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; @@ -52,7 +51,7 @@ import java.util.ArrayList; import java.util.List; import static net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype; -import static net.osmand.plus.settings.fragments.ImportSettingsFragment.IMPORT_SETTINGS_TAG; +import static net.osmand.plus.settings.fragments.BaseSettingsListFragment.SETTINGS_LIST_TAG; public class ImportDuplicatesFragment extends BaseOsmAndFragment { @@ -72,7 +71,7 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment { private SettingsHelper settingsHelper; public static void showInstance(@NonNull FragmentManager fm, List duplicatesList, - List settingsItems, File file, Fragment targetFragment) { + List settingsItems, File file, Fragment targetFragment) { ImportDuplicatesFragment fragment = new ImportDuplicatesFragment(); fragment.setTargetFragment(targetFragment, 0); fragment.setDuplicatesList(duplicatesList); @@ -80,7 +79,7 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment { fragment.setFile(file); fm.beginTransaction() .replace(R.id.fragmentContainer, fragment, TAG) - .addToBackStack(IMPORT_SETTINGS_TAG) + .addToBackStack(SETTINGS_LIST_TAG) .commitAllowingStateLoss(); } @@ -203,8 +202,8 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment { List ttsVoiceFilesList = new ArrayList<>(); List voiceFilesList = new ArrayList<>(); List mapFilesList = new ArrayList<>(); - List markersGroups = new ArrayList<>(); - List markersHistoryGroups = new ArrayList<>(); + List mapMarkers = new ArrayList<>(); + List mapMarkersGroups = new ArrayList<>(); List historyEntries = new ArrayList<>(); for (Object object : duplicatesList) { @@ -242,12 +241,12 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment { osmNotesPointList.add((OsmNotesPoint) object); } else if (object instanceof OpenstreetmapPoint) { osmEditsPointList.add((OpenstreetmapPoint) object); - } else if (object instanceof MapMarkersGroup) { - MapMarkersGroup markersGroup = (MapMarkersGroup) object; - if (ExportSettingsType.ACTIVE_MARKERS.name().equals(markersGroup.getId())) { - markersGroups.add(markersGroup); - } else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) { - markersHistoryGroups.add(markersGroup); + } else if (object instanceof MapMarker) { + MapMarker mapMarker = (MapMarker) object; + if (mapMarker.history) { + mapMarkers.add(mapMarker); + } else { + mapMarkersGroups.add(mapMarker); } } else if (object instanceof HistoryEntry) { historyEntries.add((HistoryEntry) object); @@ -313,17 +312,13 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment { duplicates.add(getString(R.string.local_indexes_cat_voice)); duplicates.addAll(voiceFilesList); } - if (!markersGroups.isEmpty()) { + if (!mapMarkers.isEmpty()) { duplicates.add(getString(R.string.map_markers)); - duplicates.addAll(markersGroups); + duplicates.addAll(mapMarkers); } - if (!markersHistoryGroups.isEmpty()) { + if (!mapMarkersGroups.isEmpty()) { duplicates.add(getString(R.string.markers_history)); - duplicates.addAll(markersHistoryGroups); - } - if (!historyEntries.isEmpty()) { - duplicates.add(getString(R.string.shared_string_search_history)); - duplicates.addAll(historyEntries); + duplicates.addAll(mapMarkersGroups); } return duplicates; } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java index 816d5517dc..18e4f3cec5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java @@ -1,45 +1,34 @@ package net.osmand.plus.settings.fragments; import android.app.Activity; -import android.content.Context; -import android.content.DialogInterface; import android.graphics.Typeface; import android.os.AsyncTask; -import android.os.Build; import android.os.Bundle; import android.text.style.StyleSpan; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.ExpandableListView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; -import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.Toolbar; -import androidx.core.view.ViewCompat; import androidx.fragment.app.FragmentManager; import com.google.android.material.appbar.CollapsingToolbarLayout; -import net.osmand.AndroidUtils; -import net.osmand.IProgress; import net.osmand.PlatformUtil; import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager.TileSourceTemplate; import net.osmand.plus.AppInitializer; import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; -import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.SQLiteTileSource; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.download.ReloadIndexesTask; +import net.osmand.plus.download.ReloadIndexesTask.ReloadIndexesListener; import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry; import net.osmand.plus.mapmarkers.MapMarker; @@ -54,7 +43,6 @@ import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem; import net.osmand.plus.settings.backend.backup.FavoritesSettingsItem; import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; -import net.osmand.plus.settings.backend.backup.SearchHistorySettingsItem; import net.osmand.plus.settings.backend.backup.HistoryMarkersSettingsItem; import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem; import net.osmand.plus.settings.backend.backup.MarkersSettingsItem; @@ -63,12 +51,11 @@ import net.osmand.plus.settings.backend.backup.OsmNotesSettingsItem; import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem; import net.osmand.plus.settings.backend.backup.ProfileSettingsItem; import net.osmand.plus.settings.backend.backup.QuickActionsSettingsItem; +import net.osmand.plus.settings.backend.backup.SearchHistorySettingsItem; 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.SettingsItem; import net.osmand.plus.settings.backend.backup.SettingsItemType; -import net.osmand.plus.widgets.TextViewEx; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -76,29 +63,25 @@ import org.apache.commons.logging.Log; import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -public class ImportSettingsFragment extends BaseOsmAndFragment { +public class ImportSettingsFragment extends BaseSettingsListFragment { public static final String TAG = ImportSettingsFragment.class.getSimpleName(); public static final Log LOG = PlatformUtil.getLog(ImportSettingsFragment.class.getSimpleName()); + private static final String DUPLICATES_START_TIME_KEY = "duplicates_start_time"; private static final long MIN_DELAY_TIME_MS = 500; - static final String IMPORT_SETTINGS_TAG = "import_settings_tag"; - private OsmandApplication app; - private ExportImportSettingsAdapter adapter; - private ExpandableListView expandableList; - private TextView description; - private List settingsItems; + private File file; - private boolean allSelected; - private boolean nightMode; - private LinearLayout buttonsContainer; - private ProgressBar progressBar; - private CollapsingToolbarLayout toolbarLayout; private SettingsHelper settingsHelper; + private List settingsItems; + + private TextView description; + private ProgressBar progressBar; + private LinearLayout buttonsContainer; + private CollapsingToolbarLayout toolbarLayout; + private long duplicateStartTime; public static void showInstance(@NonNull FragmentManager fm, @NonNull List settingsItems, @NonNull File file) { @@ -107,7 +90,7 @@ public class ImportSettingsFragment extends BaseOsmAndFragment { fragment.setFile(file); fm.beginTransaction(). replace(R.id.fragmentContainer, fragment, TAG) - .addToBackStack(IMPORT_SETTINGS_TAG) + .addToBackStack(SETTINGS_LIST_TAG) .commitAllowingStateLoss(); } @@ -117,69 +100,9 @@ public class ImportSettingsFragment extends BaseOsmAndFragment { if (savedInstanceState != null) { duplicateStartTime = savedInstanceState.getLong(DUPLICATES_START_TIME_KEY); } - app = requireMyApplication(); + exportMode = false; settingsHelper = app.getSettingsHelper(); - nightMode = !app.getSettings().isLightContent(); - requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { - @Override - public void handleOnBackPressed() { - showExitDialog(); - } - }); - } - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - inflater = UiUtilities.getInflater(app, nightMode); - View root = inflater.inflate(R.layout.fragment_import, container, false); - Toolbar toolbar = root.findViewById(R.id.toolbar); - TextViewEx continueBtn = root.findViewById(R.id.continue_button); - toolbarLayout = root.findViewById(R.id.toolbar_layout); - expandableList = root.findViewById(R.id.list); - buttonsContainer = root.findViewById(R.id.buttons_container); - progressBar = root.findViewById(R.id.progress_bar); - setupToolbar(toolbar); - ViewCompat.setNestedScrollingEnabled(expandableList, true); - View header = inflater.inflate(R.layout.list_item_description_header, null); - description = header.findViewById(R.id.description); - description.setText(R.string.select_data_to_import); - expandableList.addHeaderView(header); - 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(); - } - } - }); - if (Build.VERSION.SDK_INT >= 21) { - AndroidUtils.addStatusBarPadding21v(app, root); - } - ViewTreeObserver treeObserver = buttonsContainer.getViewTreeObserver(); - treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (buttonsContainer != null) { - ViewTreeObserver vts = buttonsContainer.getViewTreeObserver(); - int height = buttonsContainer.getMeasuredHeight(); - expandableList.setPadding(0, 0, 0, height); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - vts.removeOnGlobalLayoutListener(this); - } else { - vts.removeGlobalOnLayoutListener(this); - } - } - } - }); - return root; - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); ImportAsyncTask importTask = settingsHelper.getImportTask(); if (importTask != null) { if (settingsItems == null) { @@ -198,27 +121,24 @@ public class ImportSettingsFragment extends BaseOsmAndFragment { } } } - - adapter = new ExportImportSettingsAdapter(app, nightMode, true); - Map> itemsMap = new HashMap<>(); if (settingsItems != null) { - itemsMap = SettingsHelper.getSettingsToOperate(settingsItems, false); - adapter.updateSettingsList(itemsMap); + dataList = SettingsHelper.getSettingsToOperateByCategory(settingsItems, false); } - expandableList.setAdapter(adapter); - toolbarLayout.setTitle(getString(R.string.shared_string_import)); + } - ImportType importTaskType = settingsHelper.getImportTaskType(); - if (importTaskType == ImportType.CHECK_DUPLICATES && !settingsHelper.isImportDone()) { - updateUi(R.string.shared_string_preparing, R.string.checking_for_duplicate_description); - } else if (importTaskType == ImportType.IMPORT) { - updateUi(R.string.shared_string_importing, R.string.importing_from); - } else { - toolbarLayout.setTitle(getString(R.string.shared_string_import)); - } - if (itemsMap.size() == 1 && itemsMap.containsKey(ExportSettingsType.PROFILE)) { - expandableList.expandGroup(0); - } + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = super.onCreateView(inflater, container, savedInstanceState); + + toolbarLayout = view.findViewById(R.id.toolbar_layout); + buttonsContainer = view.findViewById(R.id.buttons_container); + progressBar = view.findViewById(R.id.progress_bar); + + description = header.findViewById(R.id.description); + description.setText(R.string.select_data_to_import); + + return view; } @Override @@ -228,11 +148,11 @@ public class ImportSettingsFragment extends BaseOsmAndFragment { } @Override - public void onResume() { - super.onResume(); - Activity activity = getActivity(); - if (activity instanceof MapActivity) { - ((MapActivity) activity).closeDrawer(); + protected void onContinueButtonClickAction() { + if (adapter.getData().isEmpty()) { + app.showShortToastMessage(getString(R.string.shared_string_nothing_selected)); + } else { + importItems(); } } @@ -251,12 +171,12 @@ public class ImportSettingsFragment extends BaseOsmAndFragment { } private void importItems() { - updateUi(R.string.shared_string_preparing, R.string.checking_for_duplicate_description); List selectedItems = getSettingsItemsFromData(adapter.getData()); if (file != null && settingsItems != null) { duplicateStartTime = System.currentTimeMillis(); settingsHelper.checkDuplicates(file, settingsItems, selectedItems, getDuplicatesListener()); } + updateUi(R.string.shared_string_preparing, R.string.checking_for_duplicate_description); } public SettingsHelper.SettingsImportListener getImportListener() { @@ -281,38 +201,29 @@ public class ImportSettingsFragment extends BaseOsmAndFragment { if (item instanceof FileSettingsItem && ((FileSettingsItem) item).getSubtype().isMap()) { Activity activity = getActivity(); if (activity instanceof MapActivity) { - new ReloadIndexesTack((MapActivity) activity).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + final WeakReference mapActivityRef = new WeakReference<>((MapActivity) activity); + ReloadIndexesListener listener = new ReloadIndexesListener() { + @Override + public void reloadIndexesStarted() { + + } + + @Override + public void reloadIndexesFinished(List warnings) { + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + mapActivity.refreshMap(); + } + } + }; + ReloadIndexesTask reloadIndexesTask = new ReloadIndexesTask(app, listener); + reloadIndexesTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } break; } } } - private static class ReloadIndexesTack extends AsyncTask { - - private final WeakReference mapActivityRef; - private final OsmandApplication app; - - ReloadIndexesTack(@NonNull MapActivity mapActivity) { - this.mapActivityRef = new WeakReference<>(mapActivity); - this.app = mapActivity.getMyApplication(); - } - - @Override - protected Void doInBackground(Void[] params) { - app.getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS, new ArrayList()); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - MapActivity mapActivity = mapActivityRef.get(); - if (mapActivity != null) { - mapActivity.refreshMap(); - } - } - } - private SettingsHelper.CheckDuplicatesListener getDuplicatesListener() { return new SettingsHelper.CheckDuplicatesListener() { @Override @@ -347,13 +258,6 @@ public class ImportSettingsFragment extends BaseOsmAndFragment { } } - private void dismissFragment() { - FragmentManager fm = getFragmentManager(); - if (fm != null && !fm.isStateSaved()) { - getFragmentManager().popBackStack(IMPORT_SETTINGS_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); - } - } - public void setSettingsItems(List settingsItems) { this.settingsItems = settingsItems; } @@ -521,39 +425,6 @@ public class ImportSettingsFragment extends BaseOsmAndFragment { return settingsItems; } - @Override - public int getStatusBarColorId() { - return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light; - } - - public void showExitDialog() { - Context themedContext = UiUtilities.getThemedContext(getActivity(), nightMode); - AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext); - dismissDialog.setTitle(getString(R.string.shared_string_dismiss)); - dismissDialog.setMessage(getString(R.string.exit_without_saving)); - dismissDialog.setNegativeButton(R.string.shared_string_cancel, null); - dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dismissFragment(); - } - }); - dismissDialog.show(); - } - - private void setupToolbar(Toolbar toolbar) { - toolbar.setNavigationIcon(getPaintedContentIcon(R.drawable.ic_action_close, nightMode - ? getResources().getColor(R.color.active_buttons_and_links_text_dark) - : getResources().getColor(R.color.active_buttons_and_links_text_light))); - toolbar.setNavigationContentDescription(R.string.shared_string_close); - toolbar.setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showExitDialog(); - } - }); - } - public void setFile(File file) { this.file = file; } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java index bc3092d963..8e4dfc14c0 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java @@ -897,7 +897,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { } private boolean nameIsEmpty() { - return changedProfile.name.trim().equals(""); + return changedProfile.name.trim().isEmpty(); } private void disableSaveButtonWithErrorMessage(String errorMessage) { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/SettingsCategoryItems.java b/OsmAnd/src/net/osmand/plus/settings/fragments/SettingsCategoryItems.java new file mode 100644 index 0000000000..2f37f9fd0e --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/SettingsCategoryItems.java @@ -0,0 +1,30 @@ +package net.osmand.plus.settings.fragments; + +import androidx.annotation.NonNull; + +import net.osmand.plus.settings.backend.ExportSettingsType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class SettingsCategoryItems { + + private final Map> itemsMap; + + public SettingsCategoryItems(@NonNull Map> itemsMap) { + this.itemsMap = itemsMap; + } + + public List getTypes() { + return new ArrayList<>(itemsMap.keySet()); + } + + public List getItemsForType(ExportSettingsType type) { + return itemsMap.get(type); + } + + public Map> getItemsMap() { + return itemsMap; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/srtmplugin/SRTMPlugin.java b/OsmAnd/src/net/osmand/plus/srtmplugin/SRTMPlugin.java index 7035a18863..a8dc02135b 100644 --- a/OsmAnd/src/net/osmand/plus/srtmplugin/SRTMPlugin.java +++ b/OsmAnd/src/net/osmand/plus/srtmplugin/SRTMPlugin.java @@ -137,9 +137,9 @@ public class SRTMPlugin extends OsmandPlugin { public boolean init(@NonNull final OsmandApplication app, Activity activity) { OsmandSettings settings = app.getSettings(); CommonPreference pref = settings.getCustomRenderProperty("contourLines"); - if (pref.get().equals("")) { + if (pref.get().isEmpty()) { for (ApplicationMode m : ApplicationMode.allPossibleValues()) { - if (pref.getModeValue(m).equals("")) { + if (pref.getModeValue(m).isEmpty()) { pref.setModeValue(m, "13"); } } @@ -456,7 +456,7 @@ public class SRTMPlugin extends OsmandPlugin { List possibleValuesList = new ArrayList<>(Arrays.asList(p.getPossibleValues())); possibleValuesList.remove(CONTOUR_LINES_DISABLED_VALUE); - final String[] possibleValues = possibleValuesList.toArray(new String[possibleValuesList.size()]); + final String[] possibleValues = possibleValuesList.toArray(new String[0]); int i = possibleValuesList.indexOf(pref.get()); if (i >= 0) { diff --git a/OsmAnd/src/net/osmand/plus/srtmplugin/TerrainFragment.java b/OsmAnd/src/net/osmand/plus/srtmplugin/TerrainFragment.java index 3635aafe89..c142ebcf5c 100644 --- a/OsmAnd/src/net/osmand/plus/srtmplugin/TerrainFragment.java +++ b/OsmAnd/src/net/osmand/plus/srtmplugin/TerrainFragment.java @@ -221,18 +221,13 @@ public class TerrainFragment extends BaseOsmAndFragment implements View.OnClickL @Override public void onClick(View view) { - switch (view.getId()) { - case R.id.switch_compat: - onSwitchClick(); - break; - case R.id.left_button: - setupTerrainMode(HILLSHADE); - break; - case R.id.right_button: - setupTerrainMode(SLOPE); - break; - default: - break; + int id = view.getId(); + if (id == R.id.switch_compat) { + onSwitchClick(); + } else if (id == R.id.left_button) { + setupTerrainMode(HILLSHADE); + } else if (id == R.id.right_button) { + setupTerrainMode(SLOPE); } } diff --git a/OsmAnd/src/net/osmand/plus/srtmplugin/TerrainLayer.java b/OsmAnd/src/net/osmand/plus/srtmplugin/TerrainLayer.java index b58dc807a8..4ffab5f7c7 100644 --- a/OsmAnd/src/net/osmand/plus/srtmplugin/TerrainLayer.java +++ b/OsmAnd/src/net/osmand/plus/srtmplugin/TerrainLayer.java @@ -114,12 +114,13 @@ public class TerrainLayer extends MapTileLayer { } private void indexNonCachedResources(Map fileModified, Map rs) { - for(String filename : fileModified.keySet()) { + for(Map.Entry entry : fileModified.entrySet()) { + String filename = entry.getKey(); try { log.info("Indexing " + type + " file " + filename); ContentValues cv = new ContentValues(); cv.put("filename", filename); - cv.put("date_modified", fileModified.get(filename)); + cv.put("date_modified", entry.getValue()); SQLiteTileSource ts = rs.get(filename); QuadRect rt = ts.getRectBoundary(ZOOM_BOUNDARY, 1); if (rt != null) { diff --git a/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java b/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java index b43cab4492..9408ec5537 100644 --- a/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java +++ b/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java @@ -86,7 +86,7 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener { } public void setTitle(String title) { - if (title.equals("")) { + if (title.isEmpty()) { if (pointDescription.isWpt()) { title = mapActivity.getString(R.string.waypoint_one); } else if (pointDescription.isRte()) { diff --git a/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java b/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java index 260f30fa50..475e7879aa 100644 --- a/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java +++ b/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java @@ -191,13 +191,13 @@ public class OsmandMapTileView implements IMapDownloaderCallback { private boolean wasZoomInMultiTouch; private float elevationAngle; - public OsmandMapTileView(MapActivity activity, int w, int h) { + public OsmandMapTileView(Activity activity, int w, int h) { this.activity = activity; init(activity, w, h); } // ///////////////////////////// INITIALIZING UI PART /////////////////////////////////// - public void init(final MapActivity ctx, int w, int h) { + public void init(final Activity ctx, int w, int h) { application = (OsmandApplication) ctx.getApplicationContext(); settings = application.getSettings(); @@ -256,7 +256,7 @@ public class OsmandMapTileView implements IMapDownloaderCallback { if (isZoomingAllowed(getZoom(), -1.1f)) { getAnimatedDraggingThread().startZooming(getZoom() - 1, currentViewport.getZoomFloatPart(), false); if (wasMapLinkedBeforeGesture) { - ctx.getMapViewTrackingUtilities().setMapLinkedToLocation(true); + application.getMapViewTrackingUtilities().setMapLinkedToLocation(true); } } } @@ -1318,7 +1318,9 @@ public class OsmandMapTileView implements IMapDownloaderCallback { angle = 90f; } this.elevationAngle = angle; - ((MapActivity) activity).setMapElevation(angle); + if (activity instanceof MapActivity) { + ((MapActivity) activity).setMapElevation(angle); + } } private boolean isZoomingAllowed(int baseZoom, float dz) { @@ -1341,7 +1343,7 @@ public class OsmandMapTileView implements IMapDownloaderCallback { @Override public boolean onDown(MotionEvent e) { // Facilitates better map re-linking for two finger tap zoom out - wasMapLinkedBeforeGesture = ((MapActivity) activity).getMapViewTrackingUtilities().isMapLinkedToLocation(); + wasMapLinkedBeforeGesture = application.getMapViewTrackingUtilities().isMapLinkedToLocation(); return false; } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/AidlMapLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/AidlMapLayer.java index 580f0c3490..df110a14cb 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/AidlMapLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/AidlMapLayer.java @@ -181,7 +181,7 @@ public class AidlMapLayer extends OsmandMapLayer implements IContextMenuProvider } if (imageRequests.size() > 0) { - executeTaskInBackground(new PointImageReaderTask(this), imageRequests.toArray(new String[imageRequests.size()])); + executeTaskInBackground(new PointImageReaderTask(this), imageRequests.toArray(new String[0])); } } mapTextLayer.putData(this, displayedPoints); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/ContextMenuLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/ContextMenuLayer.java index 7a8690fe2d..9ba3ee5f46 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/ContextMenuLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/ContextMenuLayer.java @@ -232,20 +232,22 @@ public class ContextMenuLayer extends OsmandMapLayer { if (!pressedLatLonSmall.isEmpty() || !pressedLatLonFull.isEmpty()) { textScale = activity.getMyApplication().getSettings().TEXT_SCALE.get(); } - for (LatLon latLon : pressedLatLonSmall.keySet()) { + for (Entry entry : pressedLatLonSmall.entrySet()) { + LatLon latLon = entry.getKey(); int x = (int) box.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude()); int y = (int) box.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude()); - BackgroundType background = pressedLatLonSmall.get(latLon); + BackgroundType background = entry.getValue(); Bitmap pressedBitmapSmall = background.getTouchBackground(activity, true); Rect destRect = getIconDestinationRect( x, y, pressedBitmapSmall.getWidth(), pressedBitmapSmall.getHeight(), textScale); canvas.drawBitmap(pressedBitmapSmall, null, destRect, paint); } - for (LatLon latLon : pressedLatLonFull.keySet()) { + for (Entry entry : pressedLatLonFull.entrySet()) { + LatLon latLon = entry.getKey(); int x = (int) box.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude()); int y = (int) box.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude()); - BackgroundType background = pressedLatLonFull.get(latLon); + BackgroundType background = entry.getValue(); Bitmap pressedBitmap = background.getTouchBackground(activity, false); int offsetY = background.getOffsetY(activity, textScale); Rect destRect = getIconDestinationRect( diff --git a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java index c54b6afea5..117c2a4777 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java @@ -37,9 +37,6 @@ import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; -import net.osmand.plus.mapmarkers.MapMarkersHelper; -import net.osmand.plus.mapmarkers.MapMarker; -import net.osmand.plus.mapmarkers.MapMarkersGroup; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; @@ -47,6 +44,9 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.PointImageDrawable; import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.SelectedGpxPoint; import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; +import net.osmand.plus.mapmarkers.MapMarker; +import net.osmand.plus.mapmarkers.MapMarkersGroup; +import net.osmand.plus.mapmarkers.MapMarkersHelper; import net.osmand.plus.render.OsmandRenderer; import net.osmand.plus.render.OsmandRenderer.RenderingContext; import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu; @@ -353,7 +353,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } private void drawSelectedFilesSplits(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles, - DrawSettings settings) { + DrawSettings settings) { if (tileBox.getZoom() >= START_ZOOM) { // request to load OsmandApplication app = view.getApplication(); @@ -634,7 +634,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } private void drawSelectedFilesSegments(Canvas canvas, RotatedTileBox tileBox, - List selectedGPXFiles, DrawSettings settings) { + List selectedGPXFiles, DrawSettings settings) { SelectedGpxFile currentTrack = null; for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); @@ -653,7 +653,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } private void drawSelectedFileSegments(SelectedGpxFile selectedGpxFile, boolean currentTrack, Canvas canvas, - RotatedTileBox tileBox, DrawSettings settings) { + RotatedTileBox tileBox, DrawSettings settings) { List segments = selectedGpxFile.getPointsToDisplay(); for (TrkSegment ts : segments) { String width = getTrackWidthName(selectedGpxFile.getGpxFile(), ""); @@ -1010,8 +1010,8 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM @Override public void applyNewObjectPosition(@NonNull Object o, - @NonNull LatLon position, - @Nullable final ContextMenuLayer.ApplyMovedObjectCallback callback) { + @NonNull LatLon position, + @Nullable final ContextMenuLayer.ApplyMovedObjectCallback callback) { if (o instanceof WptPt) { final WptPt objectInMotion = (WptPt) o; SelectedGpxFile selectedGpxFile = pointFileMap.get(objectInMotion); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java index 6a4cf344c7..9a24d0aba6 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java @@ -1387,7 +1387,7 @@ public class MapControlsLayer extends OsmandMapLayer { } bld.setTitle(R.string.map_magnifier); - bld.setSingleChoiceItems(values.toArray(new String[values.size()]), i, + bld.setSingleChoiceItems(values.toArray(new String[0]), i, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapTextLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapTextLayer.java index 991bed0d55..fe9d82fe99 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapTextLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapTextLayer.java @@ -61,7 +61,8 @@ public class MapTextLayer extends OsmandMapLayer { @Override public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { TIntHashSet set = new TIntHashSet(); - for (OsmandMapLayer l : textObjects.keySet()) { + for (Map.Entry> entry : textObjects.entrySet()) { + OsmandMapLayer l = entry.getKey(); MapTextProvider provider = (MapTextProvider) l; if (!view.isLayerVisible(l) || !provider.isTextVisible()) { continue; @@ -69,7 +70,7 @@ public class MapTextLayer extends OsmandMapLayer { updateTextSize(); paintTextIcon.setFakeBoldText(provider.isFakeBoldText()); - for (Object o : textObjects.get(l)) { + for (Object o : entry.getValue()) { LatLon loc = provider.getTextLocation(o); String name = provider.getText(o); if (loc == null || TextUtils.isEmpty(name)) { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java index 02671e2207..9c7fd1c782 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWay.java @@ -338,8 +338,8 @@ public abstract class GeometryWay style : styles) { if (style.hasPathLine()) { hasPathLine = true; @@ -360,7 +360,9 @@ public abstract class GeometryWay execute(List listCmd){ - Struct list = new Struct(listCmd.toArray(new Term[listCmd.size()])); + Struct list = new Struct(listCmd.toArray(new Term[0])); Var result = new Var("RESULT"); //$NON-NLS-1$ List files = new ArrayList(); if(prologSystem == null) { diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelDbHelper.java b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelDbHelper.java index 163f3483db..3acc12b79d 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelDbHelper.java @@ -217,7 +217,7 @@ public class TravelDbHelper implements TravelHelper { } query += ") "; if (params.size() > 0) { - SQLiteCursor cursor = conn.rawQuery(query, params.toArray(new String[params.size()])); + SQLiteCursor cursor = conn.rawQuery(query, params.toArray(new String[0])); if (cursor != null) { if (cursor.moveToFirst()) { do { @@ -469,7 +469,7 @@ public class TravelDbHelper implements TravelHelper { params.add(lang); } } - SQLiteCursor cursor = conn.rawQuery(query.toString(), params.toArray(new String[params.size()])); + SQLiteCursor cursor = conn.rawQuery(query.toString(), params.toArray(new String[0])); if (cursor != null && cursor.moveToFirst()) { do { WikivoyageSearchResult rs = new WikivoyageSearchResult(); diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java index dc4c7bbb8a..2419f02636 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java @@ -342,7 +342,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv res.add(item); } } - return res.toArray(new IndexItem[res.size()]); + return res.toArray(new IndexItem[0]); } @NonNull diff --git a/OsmAnd/src/org/openplacereviews/opendb/SecUtils.java b/OsmAnd/src/org/openplacereviews/opendb/SecUtils.java new file mode 100644 index 0000000000..183a93b9c0 --- /dev/null +++ b/OsmAnd/src/org/openplacereviews/opendb/SecUtils.java @@ -0,0 +1,217 @@ +//Revision d1a1f6e81d0716a47cbddf5754ee77fa5fc6d1d8 +package org.openplacereviews.opendb; + + +import android.util.Base64; +import org.openplacereviews.opendb.util.exception.FailedVerificationException; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.codec.digest.DigestUtils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.*; +import java.security.spec.EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.concurrent.ThreadLocalRandom; + +//This class is a copy of SecUtils class from OpenDB project with changes for android platform +public class SecUtils { + public static final String SIG_ALGO_SHA1_EC = "SHA1withECDSA"; + public static final String SIG_ALGO_NONE_EC = "NonewithECDSA"; + + public static final String SIG_ALGO_ECDSA = "ECDSA"; + public static final String ALGO_EC = "EC"; + + public static final String DECODE_BASE64 = "base64"; + public static final String HASH_SHA256 = "sha256"; + public static final String HASH_SHA1 = "sha1"; + + public static final String JSON_MSG_TYPE = "json"; + public static final String KEY_BASE64 = DECODE_BASE64; + + + public static EncodedKeySpec decodeKey(String key) { + if (key.startsWith(KEY_BASE64 + ":")) { + key = key.substring(KEY_BASE64.length() + 1); + int s = key.indexOf(':'); + if (s == -1) { + throw new IllegalArgumentException(String.format("Key doesn't contain algorithm of hashing to verify")); + } + //should use android.util.Base64 for android platform instead of Base64.getDecoder() + return getKeySpecByFormat(key.substring(0, s), + android.util.Base64.decode(key.substring(s + 1), Base64.DEFAULT)); + } + throw new IllegalArgumentException(String.format("Key doesn't contain algorithm of hashing to verify")); + } + + public static String encodeKey(String algo, PublicKey pk) { + if (algo.equals(KEY_BASE64)) { + return SecUtils.KEY_BASE64 + ":" + pk.getFormat() + ":" + encodeBase64(pk.getEncoded()); + } + throw new UnsupportedOperationException("Algorithm is not supported: " + algo); + } + + public static String encodeKey(String algo, PrivateKey pk) { + if (algo.equals(KEY_BASE64)) { + return SecUtils.KEY_BASE64 + ":" + pk.getFormat() + ":" + encodeBase64(pk.getEncoded()); + } + throw new UnsupportedOperationException("Algorithm is not supported: " + algo); + } + + public static EncodedKeySpec getKeySpecByFormat(String format, byte[] data) { + switch (format) { + case "PKCS#8": + return new PKCS8EncodedKeySpec(data); + case "X.509": + return new X509EncodedKeySpec(data); + } + throw new IllegalArgumentException(format); + } + + public static String encodeBase64(byte[] data) { + //should use android.util.Base64 for android platform instead of Base64.getDecoder() + return new String(android.util.Base64.decode(data, android.util.Base64.DEFAULT)); + } + + public static boolean validateKeyPair(String algo, PrivateKey privateKey, PublicKey publicKey) + throws FailedVerificationException { + if (!algo.equals(ALGO_EC)) { + throw new FailedVerificationException("Algorithm is not supported: " + algo); + } + // create a challenge + byte[] challenge = new byte[512]; + ThreadLocalRandom.current().nextBytes(challenge); + + try { + // sign using the private key + Signature sig = Signature.getInstance(SIG_ALGO_SHA1_EC); + sig.initSign(privateKey); + sig.update(challenge); + byte[] signature = sig.sign(); + + // verify signature using the public key + sig.initVerify(publicKey); + sig.update(challenge); + + boolean keyPairMatches = sig.verify(signature); + return keyPairMatches; + } catch (InvalidKeyException e) { + throw new FailedVerificationException(e); + } catch (NoSuchAlgorithmException e) { + throw new FailedVerificationException(e); + } catch (SignatureException e) { + throw new FailedVerificationException(e); + } + } + + public static KeyPair getKeyPair(String algo, String prKey, String pbKey) throws FailedVerificationException { + try { + KeyFactory keyFactory = KeyFactory.getInstance(algo); + PublicKey pb = null; + PrivateKey pr = null; + if (pbKey != null) { + pb = keyFactory.generatePublic(decodeKey(pbKey)); + } + if (prKey != null) { + pr = keyFactory.generatePrivate(decodeKey(prKey)); + } + return new KeyPair(pb, pr); + } catch (NoSuchAlgorithmException e) { + throw new FailedVerificationException(e); + } catch (InvalidKeySpecException e) { + throw new FailedVerificationException(e); + } + } + + public static String signMessageWithKeyBase64(KeyPair keyPair, byte[] msg, String signAlgo, ByteArrayOutputStream out) { + byte[] sigBytes; + try { + sigBytes = signMessageWithKey(keyPair, msg, signAlgo); + } catch (FailedVerificationException e) { + throw new IllegalStateException("Cannot get bytes"); + } + if (out != null) { + try { + out.write(sigBytes); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + String signature = Base64.encodeToString(sigBytes, Base64.DEFAULT).replace("\n", ""); + return signAlgo + ":" + DECODE_BASE64 + ":" + signature; + } + + public static byte[] signMessageWithKey(KeyPair keyPair, byte[] msg, String signAlgo) throws FailedVerificationException { + try { + //use BouncyCastle on android platform in order to achieve consistency between platforms + Signature sig = Signature.getInstance(getInternalSigAlgo(signAlgo), "BC"); + sig.initSign(keyPair.getPrivate()); + sig.update(msg); + byte[] signatureBytes = sig.sign(); + return signatureBytes; + } catch (NoSuchAlgorithmException e) { + throw new FailedVerificationException(e); + } catch (InvalidKeyException e) { + throw new FailedVerificationException(e); + } catch (SignatureException e) { + throw new FailedVerificationException(e); + } catch (NoSuchProviderException e) { + throw new RuntimeException(e); + } + } + + private static String getInternalSigAlgo(String sigAlgo) { + return sigAlgo.equals(SIG_ALGO_ECDSA) ? SIG_ALGO_NONE_EC : sigAlgo; + } + + public static byte[] calculateHash(String algo, byte[] b1, byte[] b2) { + byte[] m = mergeTwoArrays(b1, b2); + if (algo.equals(HASH_SHA256)) { + return DigestUtils.sha256(m); + } else if (algo.equals(HASH_SHA1)) { + return DigestUtils.sha1(m); + } + throw new UnsupportedOperationException(); + } + + public static byte[] mergeTwoArrays(byte[] b1, byte[] b2) { + byte[] m = b1 == null ? b2 : b1; + if (b2 != null && b1 != null) { + m = new byte[b1.length + b2.length]; + System.arraycopy(b1, 0, m, 0, b1.length); + System.arraycopy(b2, 0, m, b1.length, b2.length); + } + return m; + } + + public static String calculateHashWithAlgo(String algo, String salt, String msg) { + try { + //use Hex.encodeHex for android platform instead of Hex.encodeHexString + char[] hex = Hex.encodeHex(calculateHash(algo, salt == null ? null : salt.getBytes("UTF-8"), + msg == null ? null : msg.getBytes("UTF-8"))); + + return algo + ":" + new String(hex); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException(e); + } + } + + public static byte[] getHashBytes(String msg) { + if (msg == null || msg.length() == 0) { + // special case for empty hash + return new byte[0]; + } + int i = msg.lastIndexOf(':'); + String s = i >= 0 ? msg.substring(i + 1) : msg; + try { + return Hex.decodeHex(s.toCharArray()); + } catch (DecoderException e) { + throw new IllegalArgumentException(e); + } + } + +} diff --git a/OsmAnd/src/org/openplacereviews/opendb/ops/OpObject.java b/OsmAnd/src/org/openplacereviews/opendb/ops/OpObject.java new file mode 100644 index 0000000000..2cc8acc839 --- /dev/null +++ b/OsmAnd/src/org/openplacereviews/opendb/ops/OpObject.java @@ -0,0 +1,537 @@ +//Revision d1a1f6e81d0716a47cbddf5754ee77fa5fc6d1d8 +package org.openplacereviews.opendb.ops; + +import com.google.gson.*; +import org.openplacereviews.opendb.util.JsonObjectUtils; +// OSMAND ANDROID CHANGE BEGIN: +// removed unused imports +// OSMAND ANDROID CHANGE END + +import java.lang.reflect.Type; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +public class OpObject { + + public static final String F_NAME = "name"; + public static final String F_ID = "id"; + public static final String F_COMMENT = "comment"; + public static final String TYPE_OP = "sys.op"; + public static final String TYPE_BLOCK = "sys.block"; + public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + // transient info about validation timing etc + public static final String F_EVAL = "eval"; + public static final String F_VALIDATION = "validation"; + public static final String F_TIMESTAMP_ADDED = "timestamp"; + public static final String F_PARENT_TYPE = "parentType"; + public static final String F_PARENT_HASH = "parentHash"; + public static final String F_CHANGE = "change"; + public static final String F_CURRENT = "current"; + // voting + public static final String F_OP = "op"; + public static final String F_STATE = "state"; + public static final String F_OPEN = "open"; + public static final String F_FINAL = "final"; + public static final String F_VOTE = "vote"; + public static final String F_VOTES = "votes"; + public static final String F_SUBMITTED_OP_HASH = "submittedOpHash"; + public static final String F_USER = "user"; + + public static final OpObject NULL = new OpObject(true); + + public static SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); + static { + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + protected Map fields = new TreeMap<>(); + protected transient Map cacheFields; + protected boolean isImmutable; + + protected transient String parentType; + protected transient String parentHash; + protected transient boolean deleted; + + + public OpObject() {} + + public OpObject(boolean deleted) { + this.deleted = deleted; + } + + public OpObject(OpObject cp) { + this(cp, false); + } + + public OpObject(OpObject cp, boolean copyCacheFields) { + createOpObjectCopy(cp, copyCacheFields); + } + + @SuppressWarnings("unchecked") + private OpObject createOpObjectCopy(OpObject opObject, boolean copyCacheFields) { + this.parentType = opObject.parentType; + this.parentHash = opObject.parentHash; + this.deleted = opObject.deleted; + this.fields = (Map) copyingObjects(opObject.fields, copyCacheFields); + if (opObject.cacheFields != null && copyCacheFields) { + this.cacheFields = (Map) copyingObjects(opObject.cacheFields, copyCacheFields); + } + this.isImmutable = false; + + return this; + } + + public boolean isDeleted() { + return deleted; + } + + @SuppressWarnings("unchecked") + private Object copyingObjects(Object object, boolean copyCacheFields) { + if (object instanceof Number) { + return (Number) object; + } else if (object instanceof String) { + return (String) object; + } else if (object instanceof Boolean) { + return (Boolean) object; + } else if (object instanceof List) { + List copy = new ArrayList<>(); + List list = (List) object; + for (Object o : list) { + copy.add(copyingObjects(o, copyCacheFields)); + } + return copy; + } else if (object instanceof Map) { + Map copy = new LinkedHashMap<>(); + Map map = (Map) object; + for (Object o : map.keySet()) { + copy.put(o, copyingObjects(map.get(o), copyCacheFields)); + } + return copy; + } + // OSMAND ANDROID CHANGE BEGIN: + // removed instanceOf OpExprEvaluator + // OSMAND ANDROID CHANGE END: + else if (object instanceof OpObject) { + return new OpObject((OpObject) object); + } else { + throw new UnsupportedOperationException("Type of object is not supported"); + } + } + + public void setParentOp(OpOperation op) { + setParentOp(op.type, op.getRawHash()); + } + + public void setParentOp(String parentType, String parentHash) { + this.parentType = parentType; + this.parentHash = parentHash; + } + + public String getParentHash() { + return parentHash; + } + + public String getParentType() { + return parentType; + } + + public List getId() { + return getStringList(F_ID); + } + + public void setId(String id) { + addOrSetStringValue(F_ID, id); + } + + public boolean isImmutable() { + return isImmutable; + } + + public OpObject makeImmutable() { + isImmutable = true; + return this; + } + + public Object getFieldByExpr(String field) { + if (field.contains(".") || field.contains("[") || field.contains("]")) { + return JsonObjectUtils.getField(this.fields, generateFieldSequence(field)); + } + + return fields.get(field); + } + + + /** + * generateFieldSequence("a") - [a] + * generateFieldSequence("a.b") - [a, b] + * generateFieldSequence("a.b.c.de") - [a, b, c, de] + * generateFieldSequence("a.bwerq.c") - [a, bwerq, c] + * generateFieldSequence("a.bwerq...c") - [a, bwerq, c] + * generateFieldSequence("a.bwereq..c..") - [a, bwerq, c] + * generateFieldSequence("a.{b}") - [a, b] + * generateFieldSequence("a.{b.c.de}") - [a, b.c.de] + * generateFieldSequence("a.{b.c.de}") - [a, b.c.de] + * generateFieldSequence("a.{b{}}") - [a, b{}] + * generateFieldSequence("a.{b{}d.q}") - [a, b{}d.q] + */ + private static List generateFieldSequence(String field) { + int STATE_OPEN_BRACE = 1; + int STATE_OPEN = 0; + int state = STATE_OPEN; + int start = 0; + List l = new ArrayList(); + for(int i = 0; i < field.length(); i++) { + boolean split = false; + if (i == field.length() - 1) { + if (state == STATE_OPEN_BRACE) { + if(field.charAt(i) == '}') { + split = true; + } else { + throw new IllegalArgumentException("Illegal field expression: " + field); + } + } else { + if(field.charAt(i) != '.') { + i++; + } + split = true; + } + } else { + if (field.charAt(i) == '.' && state == STATE_OPEN) { + split = true; + } else if (field.charAt(i) == '}' && field.charAt(i + 1) == '.' && state == STATE_OPEN_BRACE) { + split = true; + } else if (field.charAt(i) == '{' && state == STATE_OPEN) { + if(start != i) { + throw new IllegalArgumentException("Illegal field expression (wrap {} is necessary): " + field); + } + state = STATE_OPEN_BRACE; + start = i + 1; + } + } + if(split) { + if (i != start) { + l.add(field.substring(start, i)); + } + start = i + 1; + state = STATE_OPEN; + } + } + return l; + } + + public void setFieldByExpr(String field, Object object) { + if (field.contains(".") || field.contains("[") || field.contains("]")) { + List fieldSequence = generateFieldSequence(field); + if (object == null) { + JsonObjectUtils.deleteField(this.fields, fieldSequence); + } else { + JsonObjectUtils.setField(this.fields, fieldSequence, object); + } + } else if (object == null) { + fields.remove(field); + } else { + fields.put(field, object); + } + } + + + public Object getCacheObject(String f) { + if(cacheFields == null) { + return null; + } + return cacheFields.get(f); + } + + public void putCacheObject(String f, Object o) { + if (isImmutable()) { + if (cacheFields == null) { + cacheFields = new ConcurrentHashMap(); + } + cacheFields.put(f, o); + } + } + + public void setId(String id, String id2) { + List list = new ArrayList(); + list.add(id); + list.add(id2); + putObjectValue(F_ID, list); + } + + public String getName() { + return getStringValue(F_NAME); + } + + public String getComment() { + return getStringValue(F_COMMENT); + } + + public Map getRawOtherFields() { + return fields; + } + + @SuppressWarnings("unchecked") + public Map getStringMap(String field) { + return (Map) fields.get(field); + } + + @SuppressWarnings("unchecked") + public Map> getMapStringList(String field) { + return (Map>) fields.get(field); + } + + @SuppressWarnings("unchecked") + public List> getListStringMap(String field) { + return (List>) fields.get(field); + } + + @SuppressWarnings("unchecked") + public List> getListStringObjMap(String field) { + return (List>) fields.get(field); + } + + @SuppressWarnings("unchecked") + public Map getStringObjMap(String field) { + return (Map) fields.get(field); + } + + @SuppressWarnings("unchecked") + public T getField(T def, String... fields) { + Map p = this.fields; + for(int i = 0; i < fields.length - 1 ; i++) { + p = (Map) p.get(fields[i]); + if(p == null) { + return def; + } + } + T res = (T) p.get(fields[fields.length - 1]); + if(res == null) { + return def; + } + return res; + } + + @SuppressWarnings("unchecked") + public Map, Object> getStringListObjMap(String field) { + return (Map, Object>) fields.get(field); + } + + + public long getDate(String field) { + String date = getStringValue(field); + // OSMAND ANDROID CHANGE BEGIN: + // removed check OUtils.isEmpty(date) + // OSMAND ANDROID CHANGE END + try { + return dateFormat.parse(date).getTime(); + } catch (ParseException e) { + return 0; + } + } + + + public void setDate(String field, long time) { + putStringValue(field, dateFormat.format(new Date(time))); + } + + public Number getNumberValue(String field) { + return (Number) fields.get(field); + } + + public int getIntValue(String key, int def) { + Number o = getNumberValue(key); + return o == null ? def : o.intValue(); + } + + public long getLongValue(String key, long def) { + Number o = getNumberValue(key); + return o == null ? def : o.longValue(); + } + + public String getStringValue(String field) { + Object o = fields.get(field); + if (o instanceof String || o == null) { + return (String) o; + } + return o.toString(); + } + + @SuppressWarnings("unchecked") + public List getStringList(String field) { + // cast to list if it is single value + Object o = fields.get(field); + if(o == null || o.toString().isEmpty()) { + return Collections.emptyList(); + } + if(o instanceof String) { + return Collections.singletonList(o.toString()); + } + return (List) o; + } + + public Object getObjectValue(String field) { + return fields.get(field); + } + + public void putStringValue(String key, String value) { + checkNotImmutable(); + if(value == null) { + fields.remove(key); + } else { + fields.put(key, value); + } + } + + /** + * Operates as a single value if cardinality is less than 1 + * or as a list of values if it stores > 1 value + * @param key + * @param value + */ + @SuppressWarnings("unchecked") + public void addOrSetStringValue(String key, String value) { + checkNotImmutable(); + Object o = fields.get(key); + if(o == null) { + fields.put(key, value); + } else if(o instanceof List) { + ((List) o).add(value); + } else { + List list = new ArrayList(); + list.add(o.toString()); + list.add(value); + fields.put(key, list); + } + } + + @SuppressWarnings("unchecked") + public Map getChangedEditFields() { + return (Map) fields.get(F_CHANGE); + } + + @SuppressWarnings("unchecked") + public Map getCurrentEditFields() { + return (Map) fields.get(F_CURRENT); + } + + public void putObjectValue(String key, Object value) { + checkNotImmutable(); + if(value == null) { + fields.remove(key); + } else { + fields.put(key, value); + } + } + + public void checkNotImmutable() { + if(isImmutable) { + throw new IllegalStateException("Object is immutable"); + } + + } + + public void checkImmutable() { + if(!isImmutable) { + throw new IllegalStateException("Object is mutable"); + } + } + + public Object remove(String key) { + checkNotImmutable(); + return fields.remove(key); + } + + public Map getMixedFieldsAndCacheMap() { + TreeMap mp = new TreeMap<>(fields); + if(cacheFields != null || parentType != null || parentHash != null) { + TreeMap eval = new TreeMap(); + + if(parentType != null) { + eval.put(F_PARENT_TYPE, parentType); + } + if(parentHash != null) { + eval.put(F_PARENT_HASH, parentHash); + } + if (cacheFields != null) { + Iterator> it = cacheFields.entrySet().iterator(); + while (it.hasNext()) { + Entry e = it.next(); + Object v = e.getValue(); + if (v instanceof Map || v instanceof String || v instanceof Number) { + eval.put(e.getKey(), v); + } + } + } + if(eval.size() > 0) { + mp.put(F_EVAL, eval); + } + } + return mp; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((fields == null) ? 0 : fields.hashCode()); + return result; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + fields + "]"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + OpObject other = (OpObject) obj; + if (fields == null) { + if (other.fields != null) + return false; + } else if (!fields.equals(other.fields)) + return false; + return true; + } + + public static class OpObjectAdapter implements JsonDeserializer, + JsonSerializer { + + private boolean fullOutput; + + public OpObjectAdapter(boolean fullOutput) { + this.fullOutput = fullOutput; + } + + @Override + public OpObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + OpObject bn = new OpObject(); + bn.fields = context.deserialize(json, TreeMap.class); + // remove cache + bn.fields.remove(F_EVAL); + return bn; + } + + @Override + public JsonElement serialize(OpObject src, Type typeOfSrc, JsonSerializationContext context) { + return context.serialize(fullOutput ? src.getMixedFieldsAndCacheMap() : src.fields); + } + + + } + + + + + + +} diff --git a/OsmAnd/src/org/openplacereviews/opendb/ops/OpOperation.java b/OsmAnd/src/org/openplacereviews/opendb/ops/OpOperation.java new file mode 100644 index 0000000000..27f2b5fb91 --- /dev/null +++ b/OsmAnd/src/org/openplacereviews/opendb/ops/OpOperation.java @@ -0,0 +1,289 @@ +//Revision d1a1f6e81d0716a47cbddf5754ee77fa5fc6d1d8 +package org.openplacereviews.opendb.ops; + +import com.google.gson.*; + +import java.lang.reflect.Type; +import java.util.*; +// OSMAND ANDROID CHANGE BEGIN: +// removed dependency OUtils +// OSMAND ANDROID CHANGE END: +public class OpOperation extends OpObject { + + public static final String F_TYPE = "type"; + public static final String F_SIGNED_BY = "signed_by"; + public static final String F_HASH = "hash"; + + public static final String F_SIGNATURE = "signature"; + + public static final String F_REF = "ref"; + public static final String F_CREATE = "create"; + public static final String F_DELETE = "delete"; + public static final String F_EDIT = "edit"; + + public static final String F_NAME = "name"; + public static final String F_COMMENT = "comment"; + + private List createdObjects = new LinkedList(); + private List editedObjects = new LinkedList(); + protected String type; + + public OpOperation() { + } + + public OpOperation(OpOperation cp, boolean copyCacheFields) { + super(cp, copyCacheFields); + this.type = cp.type; + for(OpObject o : cp.createdObjects) { + this.createdObjects.add(new OpObject(o, copyCacheFields)); + } + for(OpObject o : cp.editedObjects) { + this.editedObjects.add(new OpObject(o, copyCacheFields)); + } + } + + public String getOperationType() { + return type; + } + + public void setType(String name) { + checkNotImmutable(); + type = name; + updateObjectsRef(); + } + + protected void updateObjectsRef() { + for(OpObject o : createdObjects) { + o.setParentOp(this); + } + for(OpObject o : editedObjects) { + o.setParentOp(this); + } + } + + public String getType() { + return type; + } + + public OpOperation makeImmutable() { + isImmutable = true; + for(OpObject o : createdObjects) { + o.makeImmutable(); + } + for(OpObject o : editedObjects) { + o.makeImmutable(); + } + return this; + } + + public void setSignedBy(String value) { + putStringValue(F_SIGNED_BY, value); + } + + public void addOtherSignedBy(String value) { + super.addOrSetStringValue(F_SIGNED_BY, value); + } + + public List getSignedBy() { + return getStringList(F_SIGNED_BY); + } + + public String getHash() { + return getStringValue(F_HASH); + } + + public String getRawHash() { + String rw = getStringValue(F_HASH); + // drop algorithm and everything else + if(rw != null) { + rw = rw.substring(rw.lastIndexOf(':') + 1); + } + return rw; + } + + public List getSignatureList() { + return getStringList(F_SIGNATURE); + } + + public Map> getRef() { + return getMapStringList(F_REF); + } + + @SuppressWarnings("unchecked") + public List> getDeleted() { + List> l = (List>) fields.get(F_DELETE); + if(l == null) { + return Collections.emptyList(); + } + return l; + } + + public boolean hasDeleted() { + return getDeleted().size() > 0; + } + + public void addDeleted(List id) { + if(!fields.containsKey(F_DELETE)) { + ArrayList> lst = new ArrayList<>(); + lst.add(id); + putObjectValue(F_DELETE, lst); + } else { + getDeleted().add(id); + } + } + + public List getCreated() { + return createdObjects; + } + + public void addCreated(OpObject o) { + checkNotImmutable(); + createdObjects.add(o); + if(type != null) { + o.setParentOp(this); + } + } + + public boolean hasCreated() { + return createdObjects.size() > 0; + } + + public void addEdited(OpObject o) { + checkNotImmutable(); + editedObjects.add(o); + if (type != null) { + o.setParentOp(this); + } + } + + public List getEdited() { + return editedObjects; + } + + public boolean hasEdited() { + return editedObjects.size() > 0; + } + + + public String getName() { + return getStringValue(F_NAME); + } + + public String getComment() { + return getStringValue(F_COMMENT); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((createdObjects == null) ? 0 : createdObjects.hashCode()); + result = prime * result + ((editedObjects == null) ? 0 : editedObjects.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + OpOperation other = (OpOperation) obj; + if (createdObjects == null) { + if (other.createdObjects != null) + return false; + } else if (!createdObjects.equals(other.createdObjects)) + return false; + if (editedObjects == null) { + if (other.editedObjects != null) + return false; + } else if (!editedObjects.equals(other.editedObjects)) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + + // OSMAND ANDROID CHANGE BEGIN: + // removed unused classes and methods + // public static OpObjectDiffBuilder createDiffOperation(OpObject o) + // private static Object diffSet(Object vl) + // public static class OpObjectDiffBuilder{} + // OSMAND ANDROID CHANGE END + + public static class OpOperationBeanAdapter implements JsonDeserializer, + JsonSerializer { + + // plain serialization to calculate hash + private boolean excludeHashAndSignature; + private boolean fullOutput; + + public OpOperationBeanAdapter(boolean fullOutput, boolean excludeHashAndSignature) { + this.excludeHashAndSignature = excludeHashAndSignature; + this.fullOutput = fullOutput; + } + + public OpOperationBeanAdapter(boolean fullOutput) { + this.fullOutput = fullOutput; + this.excludeHashAndSignature = false; + } + + @Override + public OpOperation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObj = json.getAsJsonObject(); + OpOperation op = new OpOperation(); + JsonElement tp = jsonObj.remove(F_TYPE); + if(tp != null) { + String opType = tp.getAsString(); + op.type = opType; + } else { + op.type = ""; + } + JsonElement createdObjs = jsonObj.remove(F_CREATE); + if(createdObjs != null) { + JsonArray ar = createdObjs.getAsJsonArray(); + for(int i = 0; i < ar.size(); i++) { + op.addCreated((OpObject) context.deserialize(ar.get(i), OpObject.class)); + } + } + + JsonElement editedObjs = jsonObj.remove(F_EDIT); + if (editedObjs != null) { + for (JsonElement editElem : editedObjs.getAsJsonArray()) { + op.addEdited((OpObject) context.deserialize(editElem, OpObject.class)); + } + } + + jsonObj.remove(F_EVAL); + op.fields = context.deserialize(jsonObj, TreeMap.class); + return op; + } + + @Override + public JsonElement serialize(OpOperation src, Type typeOfSrc, JsonSerializationContext context) { + TreeMap tm = new TreeMap<>(fullOutput ? src.getMixedFieldsAndCacheMap() : src.fields); + if(excludeHashAndSignature) { + tm.remove(F_SIGNATURE); + tm.remove(F_HASH); + } + tm.put(F_TYPE, src.type); + + if (src.hasEdited()) { + tm.put(F_EDIT, context.serialize(src.editedObjects)); + } + + if(src.hasCreated()) { + tm.put(F_CREATE, context.serialize(src.createdObjects)); + } + return context.serialize(tm); + } + } + +} \ No newline at end of file diff --git a/OsmAnd/src/org/openplacereviews/opendb/util/JsonFormatter.java b/OsmAnd/src/org/openplacereviews/opendb/util/JsonFormatter.java new file mode 100644 index 0000000000..6603f4c3ab --- /dev/null +++ b/OsmAnd/src/org/openplacereviews/opendb/util/JsonFormatter.java @@ -0,0 +1,157 @@ +//Revision d1a1f6e81d0716a47cbddf5754ee77fa5fc6d1d8 +package org.openplacereviews.opendb.util; + +import com.google.gson.*; +// OSMAND ANDROID CHANGE BEGIN: +// removed dependency org.openplacereviews.opendb.ops.OpBlock; +// OSMAND ANDROID CHANGE END +import org.openplacereviews.opendb.ops.OpObject; +import org.openplacereviews.opendb.ops.OpOperation; +// OSMAND ANDROID CHANGE BEGIN: +// removed dependency org.springframework.stereotype.Component; +// OSMAND ANDROID CHANGE END + +import java.io.Reader; +import java.lang.reflect.Type; +import java.util.*; + +// OSMAND ANDROID CHANGE BEGIN: +// removed annotation @Component +// OSMAND ANDROID CHANGE END +public class JsonFormatter { + + private Gson gson; + + private Gson gsonOperationHash; + + private Gson gsonFullOutput; + + public JsonFormatter() { + GsonBuilder builder = new GsonBuilder(); + builder.disableHtmlEscaping(); + builder.registerTypeAdapter(OpOperation.class, new OpOperation.OpOperationBeanAdapter(false)); + builder.registerTypeAdapter(OpObject.class, new OpObject.OpObjectAdapter(false)); + // OSMAND ANDROID CHANGE BEGIN: + // removed OpBlock.class TypeAdapter + // OSMAND ANDROID CHANGE END + builder.registerTypeAdapter(TreeMap.class, new MapDeserializerDoubleAsIntFix()); + gson = builder.create(); + + builder = new GsonBuilder(); + builder.disableHtmlEscaping(); + builder.registerTypeAdapter(OpOperation.class, new OpOperation.OpOperationBeanAdapter(false, true)); + builder.registerTypeAdapter(OpObject.class, new OpObject.OpObjectAdapter(false)); + // OSMAND ANDROID CHANGE BEGIN: + // removed OpBlock.class TypeAdapter + // OSMAND ANDROID CHANGE END + builder.registerTypeAdapter(TreeMap.class, new MapDeserializerDoubleAsIntFix()); + gsonOperationHash = builder.create(); + + builder = new GsonBuilder(); + builder.disableHtmlEscaping(); + builder.registerTypeAdapter(OpOperation.class, new OpOperation.OpOperationBeanAdapter(true)); + builder.registerTypeAdapter(OpObject.class, new OpObject.OpObjectAdapter(true)); + builder.registerTypeAdapter(TreeMap.class, new MapDeserializerDoubleAsIntFix()); + gsonFullOutput = builder.create(); + + + } + + public static class MapDeserializerDoubleAsIntFix implements JsonDeserializer> { + + @Override @SuppressWarnings("unchecked") + public TreeMap deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return (TreeMap) read(json); + } + + public Object read(JsonElement in) { + + if(in.isJsonArray()){ + List list = new ArrayList(); + JsonArray arr = in.getAsJsonArray(); + for (JsonElement anArr : arr) { + list.add(read(anArr)); + } + return list; + }else if(in.isJsonObject()){ + Map map = new TreeMap(); + JsonObject obj = in.getAsJsonObject(); + Set> entitySet = obj.entrySet(); + for(Map.Entry entry: entitySet){ + map.put(entry.getKey(), read(entry.getValue())); + } + return map; + }else if(in.isJsonPrimitive()){ + JsonPrimitive prim = in.getAsJsonPrimitive(); + if(prim.isBoolean()){ + return prim.getAsBoolean(); + }else if(prim.isString()){ + return prim.getAsString(); + }else if(prim.isNumber()){ + Number num = prim.getAsNumber(); + // here you can handle double int/long values + // and return any type you want + // this solution will transform 3.0 float to long values + if(Math.ceil(num.doubleValue()) == num.longValue() && (!num.toString().contains(".") || num.toString().split("\\.")[1].length() <= 1)) + return num.longValue(); + else { + return num.doubleValue(); + } + } + } + return null; + } + } + +// operations to parse / format related + public OpOperation parseOperation(String opJson) { + return gson.fromJson(opJson, OpOperation.class); + } + + public OpObject parseObject(String opJson) { + return gson.fromJson(opJson, OpObject.class); + } + + // OSMAND ANDROID CHANGE BEGIN: + // removed unused methods + // public OpBlock parseBlock(String opJson) + // public String toJson(OpBlock bl) + // OSMAND ANDROID CHANGE END + + public JsonElement toJsonElement(Object o) { + return gson.toJsonTree(o); + } + + @SuppressWarnings("unchecked") + public TreeMap fromJsonToTreeMap(String json) { + return gson.fromJson(json, TreeMap.class); + } + + + public T fromJson(Reader json, Class classOfT) throws JsonSyntaxException { + return gson.fromJson(json, classOfT); + } + + public T fromJson(Reader json, Type typeOfT) throws JsonSyntaxException { + return gson.fromJson(json, typeOfT); + } + + public String fullObjectToJson(Object o) { + return gsonFullOutput.toJson(o); + } + + + public String opToJsonNoHash(OpOperation op) { + return gsonOperationHash.toJson(op); + } + + public String opToJson(OpOperation op) { + return gson.toJson(op); + } + + public String objToJson(OpObject op) { + return gson.toJson(op); + } + + +} diff --git a/OsmAnd/src/org/openplacereviews/opendb/util/JsonObjectUtils.java b/OsmAnd/src/org/openplacereviews/opendb/util/JsonObjectUtils.java new file mode 100644 index 0000000000..f372394c8b --- /dev/null +++ b/OsmAnd/src/org/openplacereviews/opendb/util/JsonObjectUtils.java @@ -0,0 +1,276 @@ +//Revision d1a1f6e81d0716a47cbddf5754ee77fa5fc6d1d8 +package org.openplacereviews.opendb.util; + +import java.util.*; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Class uses for work with Json Object represent as Map. + */ +public class JsonObjectUtils { + + + private static final int GET_OPERATION = 0; + private static final int SET_OPERATION = 1; + private static final int DELETE_OPERATION = 2; + protected static final Log LOGGER = LogFactory.getLog(JsonObjectUtils.class); + + private static class OperationAccess { + private final int operation; + private final Object value; + + private OperationAccess(int op, Object v) { + this.operation = op; + this.value = v; + } + + } + + /** + * Retrieve value from jsonMap by field sequence. + * @param jsonMap source json object deserialized in map + * @param fieldSequence Sequence to field value. + * Example: person.car.number have to be ["person", "car[2]", "number"] + * @return Field value + */ + public static Object getField(Map jsonMap, String[] fieldSequence) { + return accessField(jsonMap, fieldSequence, new OperationAccess(GET_OPERATION, null)); + } + + /** + * Set value to json field (path to field presented as sequence of string) + * + * @param jsonMap source json object deserialized in map + * @param fieldSequence Sequence to field value. + * * Example: person.car.number have to be ["person", "car[2]", "number"] + * @param field field value + * @return + */ + public static Object setField(Map jsonMap, List fieldSequence, Object field) { + return setField(jsonMap, fieldSequence.toArray(new String[fieldSequence.size()]), field); + } + + /** + * Set value to json field (path to field presented as sequence of string) + * + * @param jsonObject source json object deserialized in map + * @param fieldSequence Sequence to field value. + * * Example: person.car.number have to be ["person", "car[2]", "number"] + * @param field field value + * @return + */ + public static Object setField(Map jsonObject, String[] fieldSequence, Object field) { + return accessField(jsonObject, fieldSequence, new OperationAccess(SET_OPERATION, field)); + } + + + /** + * Retrieve value from jsonMap by field sequence. + * + * @param jsonObject source json object deserialized in map + * @param fieldSequence Sequence to field value. + * Example: person.car.number have to be ["person", "car[2]", "number"] + * @return Field value + */ + public static Object getField(Map jsonObject, List fieldSequence) { + return getField(jsonObject, fieldSequence.toArray(new String[fieldSequence.size()])); + } + + /** + * Delete field value from json Map (field path presented as sequence of string) + * + * @param jsonMap source json object deserialized in map + * @param fieldSequence Sequence to field value. + * Example: person.car.number have to be ["person", "car[2]", "number"] + * @return + */ + public static Object deleteField(Map jsonMap, List fieldSequence) { + return accessField(jsonMap, fieldSequence.toArray(new String[fieldSequence.size()]), new OperationAccess(DELETE_OPERATION, null)); + } + + + @SuppressWarnings("unchecked") + private static Object accessField(Map jsonObject, String[] fieldSequence, OperationAccess op) { + if (fieldSequence == null || fieldSequence.length == 0) { + throw new IllegalArgumentException("Field sequence is empty. Set value to root not possible."); + } + String fieldName = null; + Map jsonObjLocal = jsonObject; + List jsonListLocal = null; + int indexToAccess = -1; + for(int i = 0; i < fieldSequence.length; i++) { + boolean last = i == fieldSequence.length - 1; + fieldName = fieldSequence[i]; + int indOpArray = -1; + for(int ic = 0; ic < fieldName.length(); ) { + if(ic > 0 && (fieldName.charAt(ic) == '[' || fieldName.charAt(ic) == ']') && + fieldName.charAt(ic - 1) == '\\') { + // replace '\[' with '[' + fieldName = fieldName.substring(0, ic - 1) + fieldName.substring(ic); + } else if(fieldName.charAt(ic) == '[') { + indOpArray = ic; + break; + } else { + ic++; + } + } + jsonListLocal = null; // reset + if(indOpArray == -1) { + if(!last) { + Map fieldAccess = (Map) jsonObjLocal.get(fieldName); + if(fieldAccess == null) { + if(op.operation == GET_OPERATION) { + // don't modify during get operation + return null; + } + Map newJsonMap = new TreeMap<>(); + jsonObjLocal.put(fieldName, newJsonMap); + jsonObjLocal = newJsonMap; + } else { + jsonObjLocal = fieldAccess; + } + } + } else { + String arrayFieldName = fieldName.substring(0, indOpArray); + if(arrayFieldName.contains("]")) { + throw new IllegalArgumentException(String.format("Illegal field array modifier %s", fieldSequence[i])); + } + jsonListLocal = (List) jsonObjLocal.get(arrayFieldName); + if (jsonListLocal == null) { + if (op.operation == GET_OPERATION) { + // don't modify during get operation + return null; + } + jsonListLocal = new ArrayList(); + jsonObjLocal.put(arrayFieldName, jsonListLocal); + } + while (indOpArray != -1) { + fieldName = fieldName.substring(indOpArray + 1); + int indClArray = fieldName.indexOf("]"); + if (indClArray == -1) { + throw new IllegalArgumentException(String.format("Illegal field array modifier %s", fieldSequence[i])); + } + if(indClArray == fieldName.length() - 1) { + indOpArray = -1; + } else if(fieldName.charAt(indClArray + 1) == '[') { + indOpArray = indClArray + 1; + } else { + throw new IllegalArgumentException(String.format("Illegal field array modifier %s", fieldSequence[i])); + } + int index = Integer.parseInt(fieldName.substring(0, indClArray)); + if (last && indOpArray == -1) { + indexToAccess = index; + } else { + Object obj = null; + if (index < jsonListLocal.size() && index >= 0) { + obj = jsonListLocal.get(index); + } else if (op.operation == SET_OPERATION && (index == -1 || index == jsonListLocal.size())) { + index = jsonListLocal.size(); + jsonListLocal.add(null); + } else { + throw new IllegalArgumentException( + String.format("Illegal access to array at position %d", index)); + } + + if (obj == null) { + if (op.operation == GET_OPERATION) { + // don't modify during get operation + return null; + } + if (indOpArray == -1) { + obj = new TreeMap<>(); + } else { + obj = new ArrayList(); + } + jsonListLocal.set(index, obj); + } + if(indOpArray != -1) { + jsonListLocal = (List) obj; + } else { + jsonObjLocal = (Map) obj; + jsonListLocal = null; + } + } + } + + } + } + if(jsonListLocal != null) { + return accessListField(op, jsonListLocal, indexToAccess); + } else { + return accessObjField(op, jsonObjLocal, fieldName); + } + } + + private static Object accessObjField(OperationAccess op, Map jsonObjLocal, String fieldName) { + Object prevValue; + if (op.operation == DELETE_OPERATION) { + prevValue = jsonObjLocal.remove(fieldName); + } else if (op.operation == SET_OPERATION) { + prevValue = jsonObjLocal.put(fieldName, op.value); + } else { + prevValue = jsonObjLocal.get(fieldName); + } + return prevValue; + } + + private static Object accessListField(OperationAccess op, List jsonListLocal, int indexToAccess) { + Object prevValue; + int lastIndex = indexToAccess; + if (op.operation == DELETE_OPERATION) { + if (lastIndex >= jsonListLocal.size() || lastIndex < 0) { + prevValue = null; + } else { + prevValue = jsonListLocal.remove(lastIndex); + } + } else if (op.operation == SET_OPERATION) { + if (lastIndex == jsonListLocal.size() || lastIndex == -1) { + prevValue = null; + jsonListLocal.add(op.value); + } else if (lastIndex >= jsonListLocal.size() || lastIndex < 0) { + throw new IllegalArgumentException(String.format("Illegal access to %d position in array with size %d", + lastIndex, jsonListLocal.size())); + } else { + prevValue = jsonListLocal.set(lastIndex, op.value); + } + } else { + if (lastIndex >= jsonListLocal.size() || lastIndex < 0) { + prevValue = null; + } else { + prevValue = jsonListLocal.get(lastIndex); + } + } + return prevValue; + } + + @SuppressWarnings("unchecked") + public static List getIndexObjectByField(Object obj, List field, List res) { + if(obj == null) { + return res; + } + if(field.size() == 0) { + if(res == null) { + res = new ArrayList(); + } + res.add(obj); + return res; + } + if (obj instanceof Map) { + String fieldFirst = field.get(0); + Object value = ((Map) obj).get(fieldFirst); + return getIndexObjectByField(value, field.subList(1, field.size()), res); + } else if(obj instanceof Collection) { + for(Object o : ((Collection)obj)) { + res = getIndexObjectByField(o, field, res); + } + } else { + // we need extract but there no field + LOGGER.warn(String.format("Can't access field %s for object %s", field, obj)); + } + return res; + } + + +} diff --git a/OsmAnd/src/org/openplacereviews/opendb/util/exception/FailedVerificationException.java b/OsmAnd/src/org/openplacereviews/opendb/util/exception/FailedVerificationException.java new file mode 100644 index 0000000000..8826742e42 --- /dev/null +++ b/OsmAnd/src/org/openplacereviews/opendb/util/exception/FailedVerificationException.java @@ -0,0 +1,17 @@ +//Revision d1a1f6e81d0716a47cbddf5754ee77fa5fc6d1d8 +package org.openplacereviews.opendb.util.exception; + +public class FailedVerificationException extends Exception { + + private static final long serialVersionUID = -4936205097177668159L; + + + public FailedVerificationException(Exception e) { + super(e); + } + + + public FailedVerificationException(String msg) { + super(msg); + } +} \ No newline at end of file diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/CurrentPositionHelper.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/CurrentPositionHelper.java index e490925754..9be931434e 100644 --- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/CurrentPositionHelper.java +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/CurrentPositionHelper.java @@ -128,7 +128,7 @@ public class CurrentPositionHelper { } private void initCtx(SampleApplication app, List checkReaders) { - BinaryMapIndexReader[] rs = checkReaders.toArray(new BinaryMapIndexReader[checkReaders.size()]); + BinaryMapIndexReader[] rs = checkReaders.toArray(new BinaryMapIndexReader[0]); if (rs.length > 0) { RoutingConfiguration defCfg = RoutingConfiguration.getDefault().build("geocoding", 10, new HashMap()); diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleFormatter.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleFormatter.java index 9397f5ea7d..0c5780bd6a 100644 --- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleFormatter.java +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleFormatter.java @@ -12,7 +12,6 @@ import net.osmand.util.Algorithms; import java.text.DecimalFormat; import java.text.MessageFormat; -import java.util.Map.Entry; public class SampleFormatter { public final static float METERS_IN_KILOMETER = 1000f; @@ -23,7 +22,7 @@ public class SampleFormatter { public final static float FEET_IN_ONE_METER = YARDS_IN_ONE_METER * 3f; private static final DecimalFormat fixed2 = new DecimalFormat("0.00"); private static final DecimalFormat fixed1 = new DecimalFormat("0.0"); - { + static { fixed2.setMinimumFractionDigits(2); fixed1.setMinimumFractionDigits(1); fixed1.setMinimumIntegerDigits(1); @@ -275,10 +274,9 @@ public class SampleFormatter { return ""; } MapPoiTypes poiTypes = ctx.getPoiTypes(); - for(Entry e : amenity.getAdditionalInfo().entrySet()) { - String key = e.getKey(); - String vl = e.getValue(); - if(key.startsWith("name:")) { + for (String key : amenity.getAdditionalInfoKeys()) { + String vl = amenity.getAdditionalInfo(key); + if (key.startsWith("name:")) { continue; } else if(vl.length() >= 150) { if(shortDescription) { @@ -291,16 +289,15 @@ public class SampleFormatter { } else if(Amenity.WEBSITE.equals(key)) { d.append(ctx.getString("website") + ": "); } else { - AbstractPoiType pt = poiTypes.getAnyPoiAdditionalTypeByKey(e.getKey()); + AbstractPoiType pt = poiTypes.getAnyPoiAdditionalTypeByKey(key); if (pt != null) { if(pt instanceof PoiType && !((PoiType) pt).isText()) { vl = pt.getTranslation(); } else { - vl = pt.getTranslation() + ": " + amenity.unzipContent(e.getValue()); + vl = pt.getTranslation() + ": " + vl; } } else { - vl = Algorithms.capitalizeFirstLetterAndLowercase(e.getKey()) + - ": " + amenity.unzipContent(e.getValue()); + vl = Algorithms.capitalizeFirstLetterAndLowercase(key) + ": " + vl; } } d.append(vl).append('\n'); diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/builders/AmenityMenuBuilder.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/builders/AmenityMenuBuilder.java index 2215c4ad90..5719c097e8 100644 --- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/builders/AmenityMenuBuilder.java +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/builders/AmenityMenuBuilder.java @@ -39,7 +39,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; -import java.util.Map; public class AmenityMenuBuilder extends MenuBuilder { @@ -275,12 +274,11 @@ public class AmenityMenuBuilder extends MenuBuilder { List infoRows = new LinkedList<>(); List descriptions = new LinkedList<>(); - for (Map.Entry e : amenity.getAdditionalInfo().entrySet()) { + for (String key : amenity.getAdditionalInfoKeys()) { + String vl = amenity.getAdditionalInfo(key); int iconId; Drawable icon = null; int textColor = 0; - String key = e.getKey(); - String vl = e.getValue(); String textPrefix = ""; View collapsableView = null; @@ -357,7 +355,7 @@ public class AmenityMenuBuilder extends MenuBuilder { } else if (Amenity.CUISINE.equals(key)) { iconId = OsmandResources.getDrawableId("ic_action_cuisine"); StringBuilder sb = new StringBuilder(); - for (String c : e.getValue().split(";")) { + for (String c : vl.split(";")) { if (sb.length() > 0) { sb.append(", "); } else { @@ -388,7 +386,6 @@ public class AmenityMenuBuilder extends MenuBuilder { isText = true; isDescription = iconId == OsmandResources.getDrawableId("ic_action_note_dark"); textPrefix = pType.getTranslation(); - vl = amenity.unzipContent(e.getValue()); } if (!isDescription && icon == null) { icon = getRowIcon(view.getContext(), pType.getIconKeyName()); @@ -400,8 +397,7 @@ public class AmenityMenuBuilder extends MenuBuilder { iconId = OsmandResources.getDrawableId("ic_action_note_dark"); } } else { - textPrefix = Algorithms.capitalizeFirstLetterAndLowercase(e.getKey()); - vl = amenity.unzipContent(e.getValue()); + textPrefix = Algorithms.capitalizeFirstLetterAndLowercase(vl); } }