diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 7410b26a46..bca7b3f727 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,4 @@ contact_links: - name: Outdated FAQ - - url: https://groups.google.com/forum/#!forum/osmand - - about: Fix wrong or outdated FAQ on the forum instead + url: https://groups.google.com/forum/#!forum/osmand + about: Fix wrong or outdated FAQ on the forum instead diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapAddressReaderAdapter.java b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapAddressReaderAdapter.java index 18f7b2549e..8722c96acb 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapAddressReaderAdapter.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapAddressReaderAdapter.java @@ -8,6 +8,7 @@ import gnu.trove.set.hash.TIntHashSet; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -627,7 +628,9 @@ public class BinaryMapAddressReaderAdapter { indexOffset = codedIS.getTotalBytesRead(); int oldLimit = codedIS.pushLimit(length); // here offsets are sorted by distance - map.readIndexedStringTable(stringMatcher.getCollator(), req.nameQuery, "", loffsets, 0); + TIntArrayList charsList = new TIntArrayList(); + charsList.add(0); + map.readIndexedStringTable(stringMatcher.getCollator(), Collections.singletonList(req.nameQuery), "", Collections.singletonList(loffsets), charsList); codedIS.popLimit(oldLimit); break; case OsmAndAddressNameIndexData.ATOM_FIELD_NUMBER: 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 8743940a74..dc16b89f30 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java @@ -2161,9 +2161,9 @@ public class BinaryMapIndexReader { private static boolean testAddressSearch = false; private static boolean testAddressSearchName = false; private static boolean testAddressJustifySearch = false; - private static boolean testPoiSearch = false; + private static boolean testPoiSearch = true; private static boolean testPoiSearchOnPath = false; - private static boolean testTransportSearch = true; + private static boolean testTransportSearch = false; private static int sleft = MapUtils.get31TileNumberX(27.55079); private static int sright = MapUtils.get31TileNumberX(27.55317); @@ -2177,7 +2177,7 @@ public class BinaryMapIndexReader { public static void main(String[] args) throws IOException { File fl = new File(System.getProperty("maps") + "/Synthetic_test_rendering.obf"); - fl = new File("/home/madwasp79/OsmAnd-maps/Poly_center2.obf"); + fl = new File(System.getProperty("maps") +"/Wikivoyage.obf__"); RandomAccessFile raf = new RandomAccessFile(fl, "r"); @@ -2325,7 +2325,7 @@ public class BinaryMapIndexReader { private static void testPoiSearchByName(BinaryMapIndexReader reader) throws IOException { println("Searching by name..."); - SearchRequest req = buildSearchPoiRequest(0, 0, "Art", + SearchRequest req = buildSearchPoiRequest(0, 0, "central ukraine", 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, null); reader.searchPoiByName(req); @@ -2385,54 +2385,72 @@ public class BinaryMapIndexReader { } - int readIndexedStringTable(Collator instance, String query, String prefix, TIntArrayList list, int charMatches) throws IOException { + void readIndexedStringTable(Collator instance, List queries, String prefix, List listOffsets, TIntArrayList matchedCharacters) throws IOException { String key = null; + boolean[] matched = new boolean[matchedCharacters.size()]; + boolean shouldWeReadSubtable = false; while (true) { int t = codedIS.readTag(); int tag = WireFormat.getTagFieldNumber(t); switch (tag) { case 0: - return charMatches; + return; case OsmandOdb.IndexedStringTable.KEY_FIELD_NUMBER : key = codedIS.readString(); - if(prefix.length() > 0){ + if (prefix.length() > 0) { key = prefix + key; } - // check query is part of key (the best matching) - if(CollatorStringMatcher.cmatches(instance, key, query, StringMatcherMode.CHECK_ONLY_STARTS_WITH)){ - if(query.length() >= charMatches){ - if(query.length() > charMatches){ - charMatches = query.length(); - list.clear(); - } - } else { - key = null; + shouldWeReadSubtable = false; + for (int i = 0; i < queries.size(); i++) { + int charMatches = matchedCharacters.get(i); + String query = queries.get(i); + matched[i] = false; + if (query == null) { + continue; } - // check key is part of query - } else if (CollatorStringMatcher.cmatches(instance, query, key, StringMatcherMode.CHECK_ONLY_STARTS_WITH)) { - if (key.length() >= charMatches) { - if (key.length() > charMatches) { - charMatches = key.length(); - list.clear(); + + // check query is part of key (the best matching) + if (CollatorStringMatcher.cmatches(instance, key, query, StringMatcherMode.CHECK_ONLY_STARTS_WITH)) { + if (query.length() >= charMatches) { + if (query.length() > charMatches) { + matchedCharacters.set(i, query.length()); + listOffsets.get(i).clear(); + } + matched[i] = true; + } + // check key is part of query + } else if (CollatorStringMatcher.cmatches(instance, query, key, StringMatcherMode.CHECK_ONLY_STARTS_WITH)) { + if (key.length() >= charMatches) { + if (key.length() > charMatches) { + matchedCharacters.set(i, key.length()); + listOffsets.get(i).clear(); + } + matched[i] = true; } - } else { - key = null; } - } else { - key = null; + shouldWeReadSubtable |= matched[i]; } break; case OsmandOdb.IndexedStringTable.VAL_FIELD_NUMBER : int val = readInt(); - if (key != null) { - list.add(val); + for (int i = 0; i < queries.size(); i++) { + if (matched[i]) { + listOffsets.get(i).add(val); + } } break; case OsmandOdb.IndexedStringTable.SUBTABLES_FIELD_NUMBER : int len = codedIS.readRawVarint32(); int oldLim = codedIS.pushLimit(len); - if (key != null) { - charMatches = readIndexedStringTable(instance, query, key, list, charMatches); + if (shouldWeReadSubtable && key != null) { + List subqueries = new ArrayList<>(queries); + // reset query so we don't search what was not matched + for(int i = 0; i < queries.size(); i++) { + if(!matched[i]) { + subqueries.set(i, null); + } + } + readIndexedStringTable(instance, subqueries, key, listOffsets, matchedCharacters); } else { codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); } 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 cb348cf9b4..fd6fe7bce9 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java @@ -1,10 +1,6 @@ package net.osmand.binary; -import gnu.trove.list.array.TIntArrayList; -import gnu.trove.map.hash.TIntLongHashMap; -import gnu.trove.set.hash.TLongHashSet; - import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -12,6 +8,14 @@ import java.util.Comparator; import java.util.LinkedList; import java.util.List; +import org.apache.commons.logging.Log; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.WireFormat; + +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TIntLongHashMap; +import gnu.trove.set.hash.TLongHashSet; import net.osmand.Collator; import net.osmand.CollatorStringMatcher; import net.osmand.CollatorStringMatcher.StringMatcherMode; @@ -26,11 +30,6 @@ import net.osmand.osm.MapPoiTypes; import net.osmand.osm.PoiCategory; import net.osmand.util.MapUtils; -import org.apache.commons.logging.Log; - -import com.google.protobuf.CodedInputStream; -import com.google.protobuf.WireFormat; - public class BinaryMapPoiReaderAdapter { private static final Log LOG = PlatformUtil.getLog(BinaryMapPoiReaderAdapter.class); @@ -38,7 +37,7 @@ public class BinaryMapPoiReaderAdapter { private static final int CATEGORY_MASK = (1 << SHIFT_BITS_CATEGORY) - 1; private static final int ZOOM_TO_SKIP_FILTER_READ = 6; private static final int ZOOM_TO_SKIP_FILTER = 3; - private static final int BUCKET_SEARCH_BY_NAME = 5; + private static final int BUCKET_SEARCH_BY_NAME = 15; // should be bigger 100? public static class PoiSubType { public boolean text; @@ -332,7 +331,7 @@ public class BinaryMapPoiReaderAdapter { }); int p = BUCKET_SEARCH_BY_NAME * 3; if (p < offKeys.length) { - for (int i = p + BUCKET_SEARCH_BY_NAME; ; i += BUCKET_SEARCH_BY_NAME) { + for (int i = p + BUCKET_SEARCH_BY_NAME;; i += BUCKET_SEARCH_BY_NAME) { if (i > offKeys.length) { Arrays.sort(offKeys, p, offKeys.length); break; @@ -344,7 +343,6 @@ public class BinaryMapPoiReaderAdapter { } } - LOG.info("Searched poi structure in " + (System.currentTimeMillis() - time) + "ms. Found " + offKeys.length + " subtrees"); for (int j = 0; j < offKeys.length; j++) { @@ -370,7 +368,8 @@ public class BinaryMapPoiReaderAdapter { private TIntLongHashMap readPoiNameIndex(Collator instance, String query, SearchRequest req) throws IOException { TIntLongHashMap offsets = new TIntLongHashMap(); - TIntArrayList dataOffsets = null; + List listOffsets = null; + List listOfSepOffsets = new ArrayList(); int offset = 0; while (true) { int t = codedIS.readTag(); @@ -381,24 +380,51 @@ public class BinaryMapPoiReaderAdapter { case OsmandOdb.OsmAndPoiNameIndex.TABLE_FIELD_NUMBER: { int length = readInt(); int oldLimit = codedIS.pushLimit(length); - dataOffsets = new TIntArrayList(); offset = codedIS.getTotalBytesRead(); - map.readIndexedStringTable(instance, query, "", dataOffsets, 0); + List queries = new ArrayList<>(); + for (String word : query.split(" ")) { + if (word.trim().length() > 0) { + queries.add(word.trim()); + } + } + TIntArrayList charsList = new TIntArrayList(queries.size()); + listOffsets = new ArrayList(queries.size()); + while(listOffsets.size() < queries.size()) { + charsList.add(0); + listOffsets.add(new TIntArrayList()); + } + map.readIndexedStringTable(instance, queries, "", listOffsets, charsList); codedIS.popLimit(oldLimit); break; } case OsmandOdb.OsmAndPoiNameIndex.DATA_FIELD_NUMBER: { - if (dataOffsets != null) { - dataOffsets.sort(); // 1104125 - for (int i = 0; i < dataOffsets.size(); i++) { - codedIS.seek(dataOffsets.get(i) + offset); - int len = codedIS.readRawVarint32(); - int oldLim = codedIS.pushLimit(len); - readPoiNameIndexData(offsets, req); - codedIS.popLimit(oldLim); - if (req.isCancelled()) { - codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); - return offsets; + if (listOffsets != null) { + for (TIntArrayList dataOffsets : listOffsets) { + TIntLongHashMap offsetMap = new TIntLongHashMap(); + listOfSepOffsets.add(offsetMap); + dataOffsets.sort(); // 1104125 + for (int i = 0; i < dataOffsets.size(); i++) { + codedIS.seek(dataOffsets.get(i) + offset); + int len = codedIS.readRawVarint32(); + int oldLim = codedIS.pushLimit(len); + readPoiNameIndexData(offsetMap, req); + codedIS.popLimit(oldLim); + if (req.isCancelled()) { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return offsets; + } + } + } + } + if (listOfSepOffsets.size() > 0) { + offsets.putAll(listOfSepOffsets.get(0)); + for (int j = 1; j < listOfSepOffsets.size(); j++) { + TIntLongHashMap mp = listOfSepOffsets.get(j); + // offsets.retainAll(mp); -- calculate intresection of mp & offsets + for (int chKey : offsets.keys()) { + if (!mp.containsKey(chKey)) { + offsets.remove(chKey); + } } } } diff --git a/OsmAnd/res/drawable/ic_action_multi_download.xml b/OsmAnd/res/drawable/ic_action_multi_download.xml new file mode 100644 index 0000000000..13c1b8bcba --- /dev/null +++ b/OsmAnd/res/drawable/ic_action_multi_download.xml @@ -0,0 +1,20 @@ + + + + + diff --git a/OsmAnd/res/values-ar/strings.xml b/OsmAnd/res/values-ar/strings.xml index d12d0a4de4..48e89e070c 100644 --- a/OsmAnd/res/values-ar/strings.xml +++ b/OsmAnd/res/values-ar/strings.xml @@ -329,7 +329,7 @@ نسخ الاحتياطي كتعديل OSM %1$d ملف بقى يظهر الإعدادات لتمكين التتبع والملاحة في وضعية السكون ( الشاشة مغلقة ) عبر إيقاظ دوري لجهاز GPS. - تمكين لحساب المسارات بدقة دون أخطاء. لا يزال محدود المسافة وبطيء. + حساب الطرق بدقة دون أخطاء. لا يزال محدود المسافة وبطيء. صورة %1$s %2$s مزامنة المسارات والملاحظات الصوتية / الفيديو مع حساب Dropbox الخاص بك. تنسيق الفيديو الناتج: @@ -471,7 +471,7 @@ إفريقيا آسيا أستراليا و أوقيانوسيا - التوجيه مع الطرق + التوجيه ضبط خاص لكل وضع من أوضاع الملاحة. إدارة بيانات الخرائط إعدادات عامة @@ -977,7 +977,7 @@ مصدر الخريطة عرض أسماء المفضلة لغة الخريطة - تفاصيل إضافية + التفاصيل الوقت الحالي اتجاه الخريطة اتجاه الحركة في الأعلى @@ -992,7 +992,7 @@ تسجيل المسار اختر الفاصل الزمني لتسجيل المسار أثناء الملاحة صوت مسج - التوجيه مع الطرق + الاتجاهات استخدام الموقع… مفضلة نقاط مفضلة مجاورة @@ -1071,7 +1071,7 @@ تجنب الطرق… طرق السكك الحديدية خطوط الترام - المسارات الرياضية + الطرق وسائل المواصلات سمات أخرى للخريطة العناصر الأخرى @@ -1170,7 +1170,7 @@ طرق الحافلات الكهربائية طرق الحافلات سكك قطار الأنفاق - شارك طرق التاكسي + تاكسي مشاركة الطرق حدد حد السرعة المسموح به لتلقي تنبيه صوتي إذا ما تجاوزته. مراقبة الحدود كشك الرسوم @@ -1184,7 +1184,7 @@ قيود الدخول عرض قيود الدخول عرض سطح الطريق - إظهار مسارات الدراجات + إظهار طرق الدراجات بدء التوجيه المفصل تلقائياً مسارات فرعية: %1$s نقاط الطريق: %1$s @@ -1390,7 +1390,7 @@ قطار المسار الحالي مستوى البطارية - تغيير موقع التوجيه المباشر + تغيير موقع العلامة تابعنا اتجاه صدى الصوت الملاحة عبر أوسماند لايف @@ -1411,7 +1411,7 @@ مظهرالخريطة رقيقة متوسط - لم تضف توجيه مباشر على الخريطة + أضف علامات عبر الخريطة لم يتم العثور على نقاط الطريق التقرير سمح الآن للتطبيق بالكتابة على وحدة التخزين الخارجية. الرجاء إعادة تشغيله يدويا. @@ -1436,7 +1436,7 @@ رفع كمستخدم مجهول رفع ملاحظة OSM شريط الأدوات - حدد توجيه مباشرعلى الخريطة + حدد علامات الخريطة ترتيب عكسي تفعيل ميزة العلامات. الأسترية @@ -1472,7 +1472,7 @@ حرف غير قانوني في اسم الملف تقرير عن خرائط العالم - حرك الخريطة لتغيير مكان التوجيه المباشر + حرك الخريطة لتغيير مكان العلامة إشارة صوتية عند اتجاه نقطة الوصول. حدد اتجاه النقطة المستهدفة بالاهتزاز. @@ -1590,7 +1590,7 @@ حرك للاسفل اسم مستخدم و كلمة سر OSM نحن بحاجة اليه لكي نوفر لك معلومات حول المساهمات. - حدد توجيه مباشر + اختر علامة عرض شريط الشفافية لا توجد مساحة كافية! \n {3} MB مطلوب مؤقتا ، {1} ميجا بايت بشكل دائم. @@ -1611,7 +1611,7 @@ \nللعودة إلى واحدة من أنماط الخريطة التقليدية، ببساطة إما عطل هذا الملحق مرة أخرى أو غير \'نمط الخريطة\' في \'ضبط الخريطة\' حسب الرغبة. البحث قرب مركز الخريطة الحالية عدد خطوط التوجيه - التوجيه المباشر + علامات الخريطة تخطي الحدود حدد الطرق التي تريد تجنبها أثناء التنقل. الفئات @@ -1629,11 +1629,11 @@ الخرائط الموجودة انتقال للأعلى التعديلات %1$s ، الرتبة %2$s ، مجموع التعديلات %3$s - التوجيه المباشرالأول للخريطة - التوجيه المباشرالثاني للخريطة - إضافة إلى التوجيه المباشر - حذف كافة التوجيه المباشرالنشط على الخريطة؟ - توجيه مباشر على الخريطة + أول علامة + ثاني علامة + إضافة إلى علامات الخريطة + حذف كافة العلامات النشطة على الخريطة؟ + علامة خريطة عرض المضلعات الحالة حفظ التعديلات @@ -1655,7 +1655,7 @@ اختر التوجيه الصوتي اختر أو قم بتحميل التوجيه الصوتي الخاص بلغتك. منح الوصول إلى بيانات الموقع. - مسارات الخيول + طرق الخيول إخفاء جودة أقل أعلى جودة @@ -1749,7 +1749,7 @@ خطأ تحيين القائمة المحلية لPOI. تحيين الPOI قم بتحميل مذكرة OSM الخاصة بك دون الكشف عن هويتك أو باستخدام ملف تعريف OpenStreetMap.org . - إضافة جميع النقاط إلى التوجيه المباشر؟ + إضافة جميع النقاط إلى علامات الخريطة؟ مسح السجلات ؟ إظهار مسارات الدراجة الجبلية يمكنك إزالة التحديثات المحملة والرجوع إلى الإصدار الأصلي للخريطة @@ -1830,7 +1830,7 @@ ملاحظة OSM معلق عليها مسار زلق لإظهار خرائط التزلج، يجب تحميل خريطة خاصة محلية. - حافلة، ترامواي وغيرها + حافلة، عربة وغيرها إنشاء ملاحظة OSM حدث استثناء: لم يتم إنشاء الملاحظة. حدث استثناء: لم يتم غلق الملاحظة. @@ -1868,7 +1868,7 @@ تلوين وفق الانتماء للشبكة تلوين وفق رمز تنزه OSMC خروج - هل أنت متأكد من أنك تريد حذف الملاحظات %1$d؟ + حذف الملاحظات %1$d؟ لعرض الخرائط البحرية، يجب تحميل خريطة خاصة محلياً. تسجيل الموقع العام إلى ملف GPX يمكن تشغيله أو إيقافه باستخدام نافذة تسجيل GPX على الشاشة خريطة. ضبط اسم مضيف البروكسي (مثال 127.0.0.1). @@ -2089,7 +2089,7 @@ إجراءات سريعة إجراء %d شاشة %d - إضافة توجيه مباشر للخريطة + إضافة علامة خريطة إضافة POI نمط الخريطة نمط الخرائط تغير ل \"%s\". @@ -2468,7 +2468,7 @@ إضافة نقطة قبل إضافة نقطة بعد خيارات - سيتم توصيل النقاط بمسارات الوضع المحدد. + سيتم توصيل النقاط بطرق الوضع المحدد. يمكنك حفظ النقاط إما كنقاط طريق أو كخط. اختر وضع الملاحة إضافة نقاط مسار @@ -2481,12 +2481,12 @@ عتبة توجيه الخريطة حدد أدناه على أي سرعة يتغير توجيه الخريطة من \'اتجاه الحركة\' إلى \'البوصلة\'. تم نقل جميع العلامات إلى السجل - تم نقل التوجيه المباشر إلى السجل - التوجيه المباشر انتقل كنشط + تم نقل العلامة إلى السجل + العلامة أصبحت نشطة قائمة مجموعات آخر استخدام : %1$s - تنشيط التوجيه المباشر + تنشيط العلامة اليوم أمس آخر ٧ أيام @@ -2502,12 +2502,12 @@ سهم متجه للهدف عرض المتجاوز إخفاء المتجاوز - إزالة من \"التوجيه المباشر\" + إزالة من \"علامات الخريطة\" تنازلي تصاعدي تاريخ الإضافة ترتيب حسب: - حدد كيفية الإشارة إلى المسافة والاتجاه للتوجيه المباشر على شاشة الخريطة: + حدد كيفية الإشارة إلى مسافة واتجاه العلامة على شاشة الخريطة: استخدم الموقع أضف موقعك كنقطة أولى لتخطيط طريق مثالي. موقعي @@ -2518,7 +2518,7 @@ تصدير علاماتك إلى ملف يمكنك تحديده هنا: نقل إلى السجل سيتم إزالة المجموعة بعد إعادة تشغيل التطبيق. - التوجيه المباشر + العلامات نمط الإحداثيات لوحة مفاتيح النظام اختر نسق إدخال الأحداثيات. يمكنك دائماً تغييره بالنقر على خيارات. @@ -2535,12 +2535,12 @@ أظهر الخريطة تم حساب المسار رحلة ذهاب وإياب - يجب عليك إضافة توجيه مباشر واحد على الأقل لاستخدام هذه الوظيفة. + يجب عليك إضافة علامة واحدة على الأقل لاستخدام هذه الوظيفة. تنسيق خاطئ أدخل اسم جديد عودة عرض - تمت إضافة نقاط الطريق إلى التوجيه المباشر للخريطة + تمت إضافة نقاط الطريق إلى علامات الخريطة إدخال خاطئ يمكن استيرادها كنقاط مفضلة، أو كملف GPX. استيراد كملف GPX @@ -2548,15 +2548,15 @@ استيراد ملف نقرة على الخريطة ستفعل أزرار التحكم والويدجت. شاشة كاملة - توجيه مباشر مجتاز + علامة مُجتازة إنشاء أو تعديل عناصر OSM قم بإنشاء أو تعديل نقاط الاهتمام OSM ، وفتح ملاحظات OSM أو التعليق عليها ، والمساهمة في ملفات GPX المسجلة. حذف مُعدلة تمت الإضافة تعديل طلب البحث. - تم تنشيط التوجيه المباشر %s. - انقر على التوجيه المباشر في الخريطة لجعله الاعلى بدون فتح القائمة. + تم تنشيط العلامة %s. + انقر على العلامة في الخريطة لجعلها بالاعلى بدون فتح القائمة. تدوين ملاحظات! بدون حد زمني اقرأ المقال كاملا @@ -2564,27 +2564,27 @@ جميع نقاط هذه المجموعة افتح من مفتوح حتى - يغلق أبوابه على - سيفتح الأبواب على - يفتح أبوابه على + يغلق عند + يفتح عند + يفتح عند إجراءات إضافية إجراءات - توجيه مباشر + العلامات الملاحظات حسب التاريخ حسب التاريخ حسب النوع المزيد - التوجيه المباشر + المظهر على الخريطة نقاط المسار إضافة مجموعة - قم بإنشاء التوجيه المباشر على الخريطة ! + قم بإنشاء علامات على الخريطة ! استيراد مجموعات عدد الأرقام اليمين اليسار لصق الانتقال إلى الحقل التالي - إعادة تسمية التوجيه المباشر + إعادة تسمية العلامة مجموع التبرعات تسميات POI بدون اسم @@ -2616,7 +2616,7 @@ ج ش اسم النقطة - الطرق القريبة التي في الداخل + الطرق القريبة في الداخل أدخل اسم الملف. خطأ أثناء استرجاع الخريطة تمت عملية استيراد الخريطة @@ -2628,7 +2628,7 @@ قم باختيار نسق الملف جميع البيانات ملاحظات OSM - سيفتح أبوابه غداً على + سيفتح غداً عند ماذا هنا: اللاوسية عرض خريطة السياحة @@ -2692,7 +2692,7 @@ تنزيل الكل إعادة تشغيل التطبيق إشارة مرجعية - نقاط بالطريق تم إزالتها من التوجيه المباشر للخريطة + نقاط بالطريق تم إزالتها من علامات الخريطة بواسطة أوسماند الأسعار والاشتراك شهري @@ -2707,14 +2707,14 @@ يجدد سنويا حدد فترة الدفع المناسبة لك: تبرعات مساعدة صندوق رسم الخرائط OSM. - حذف التوجيه المباشر \'%s\'؟ - تعديل التوجيه المباشر + حذف العلامة \'%s\'؟ + تعديل العلامة بحث عن شارع اختر المدينة أولاً استعادة تطبيق من طرف ثالث - عند التفعيل سيبقى التوجيه المباشر المضاف من مجموعة إحداثيات أو من نقاط طريق على الخريطة عند اختيار \"تجاوز التوجيه المباشر\". إذا كانت المجموعة غير نشطة ستختفي الوجهات المباشرة من الخريطة. - إبقاء التوجيه المباشر المتجاوز + ستبقى العلامات المضافة من مجموعة إحداثيات أو من نقاط طريق على الخريطة عند اختيار \"تجاوز العلامة\". إذا كانت المجموعة غير نشطة ستختفي العلامات من الخريطة. + إبقاء العلامة المتجاوز هناك المزيد من وسائل النقل في هذا الموقف. يرجى إعطاء إذن تحديد الموقع للتطبيق لكي يواصل. شكرا على الرد @@ -2842,7 +2842,7 @@ إضافة ملاحظة صوتية أو فيديو أو صورة لكل نقطة على الخريطة، باستخدام قائمة السياق أو القطعة. ابحث عن المسارات مع نقاط الطريق حدد مسار لإضافة نقاط الطريق إلى العلامات(يتم سرد المسارات فقط مع نقاط الطريق). - نقرة طويلة أو قصيرة على الأماكن ثم اضغط على زر التوجيه المباشر. + نقرة طويلة أو قصيرة على الأماكن ثم اضغط على زر علامة. يمكنك استيراد المجموعات المفضلة أو نقاط المسار كتوجيه. ستظهر العلامات التي تم تجاوزها على هذه الشاشة. خط مباشر من موقعك إلى الهدف. @@ -2992,7 +2992,7 @@ سنوات ثلاثة أشهر مجاناً - إظهار شبكة مسارات الدارجات الهوائية + إظهار شبكة طرق الدارجات الهوائية نافذة تحميل الخريطة النوافذ والإشعارات التحكم في النوافذ المنبثقة ، ومربعات الحوار والإشعارات. @@ -3017,7 +3017,7 @@ لصق مسار مجلد بيانات أوسماند تغيير مجلد التخزين ؟ نقل للموقع الجديد - تجنب بعض الطرق + تجنب بعض أنواع الطرق جنبًا إلى جنب طريق تلفريك اتصال @@ -3042,7 +3042,7 @@ تفضيل الطرق الغير معبدة تفضيل الطرق الغير معبدة. تحديث كل الخرائط - هل أنت متأكد من رغبتك بتحديث (%1$d) خريطة؟ + تحديث (%1$d) خريطة؟ • تحديث التطبيق وإعدادات الأوضاع: يتم ترتيب الإعدادات الآن حسب النوع. يمكن تخصيص كل وضع بشكل منفصل. \n \n • نافذة جديدة لتنزيل الخريطة المقترحة أثناء تصفح الخرائط @@ -3328,14 +3328,14 @@ طرق لجولات التزلج. تزلج منحدرات لاستخدام الزلاجات. - السماح بالمسارات المتوسطة - طرق أكثر صعوبة مع أقسام أكثر حدة. بعض العقبات التي ينبغي تجنبها. + السماح بالطرق المتوسطة + طرق أكثر صعوبة مع أقسام أكثر حدة. بعض العقبات ينبغي تجنبها. السماح للطرق المتقدمة طرق صعبة ، مع عقبات خطيرة وأقسام شديدة الانحدار. السماح بطرق المتخصصين طرق صعبة للغاية ، مع عقبات خطيرة والمناطق المحيطة بها. السماح بالتزلج على الطرق فقط - الطريق مصممة خصيصا بحرية أو التزلج على الجليد. + طرق مصممة للأسلوب الحر أو التزلج فقط بدون المسارات الكلاسيكية. السماح للطرق الكلاسيكية فقط تم إعداد الطرق للأسلوب الكلاسيكي فقط دون مسارات التزلج. يشمل ذلك الطرق التي يتم إعدادها بواسطة عربة ثلجية أصغر مع زحلقة مرنة ومسارات مصنوعة يدوياً بواسطة المتزلجين. الصعوبة المفضلة @@ -3355,8 +3355,8 @@ لوحة المفاتيح وندرلينك ببغاء - المسار: المسافة%2$s، وقت التوجيه %1$s. -\nالحساب: %3$.1f ث، %4$d طريق، %5$d تجانب) + "المسار: المسافة%1$s، الوقت %2$s. +\nالحساب: %3$.1f ث، %4$d طريق، %5$d تجانب" الأوكيتانية ثم %1$s تطبيق فقط على \"%1$s\" @@ -3378,7 +3378,7 @@ اختر اللون لا يمكنك حذف أوضاع أوسماند الافتراضية ، ولكن يمكنك تعطيلها في الشاشة السابقة ، أو نقلها إلى الأسفل. تحرير الأوضاع - يؤثر نوع التنقل على قواعد حسابات المسار. + يؤثر نوع التنقل على قواعد حساب الطرق. مظهر الوضع اختر الايقونة واللون والاسم تحرير قائمة الأوضاع @@ -3534,7 +3534,7 @@ استعادة جميع إعدادات الوضع؟ حفظ الوضع الجديد لا يمكن عمل نسخة احتياطية لهذا الوضع. - هل أنت متأكد من أنك تريد مسح البيانات المسجلة؟ + مسح البيانات المسجلة؟ استيراد البيانات من %1$s استيراد OsmAnd تحقق %1$s للتكرارات مع العناصر الموجودة في التطبيق. @@ -3730,7 +3730,7 @@ مهلة الشاشة الافتراضية يمكنك تصدير أو استيراد إجراءات سريعة باستخدام أوضاع التطبيق . حذف الكل؟ - هل أنت متأكد من رغبتك في حذف الاختصارات السريعة %d نهائيًا؟ + حذف الاختصارات السريعة %d نهائيًا؟ مهلة الشاشة نغمات أدل بعرض مركبتك، قد يتم تطبيق بعض القيود على المركبات العريضة. @@ -3787,7 +3787,7 @@ أغلق ملاحظة OSM تحتاج إلى تعيين أيام العمل للمتابعة المسار بين النقاط - قياس المسافة + تخطيط طريق إضافة إلى مسار لن تكون النقطة المضافة مرئية على الخريطة، نظرًا لأن المجموعة المحددة مخفية، يمكنك العثور عليها في \"%s\". إظهار رموز البدء والانتهاء @@ -3816,7 +3816,7 @@ بعد ذلك ، ألقط مسارك بأقرب طريق مسموح به باستخدام أحد أوضاع التنقل الخاصة بك لاستخدام هذا الخيار. بداية المسافة صور للشارع - هل أنت متأكد أنك تريد إغلاق مسار الرحلة دون حفظ؟ سوف تفقد كل التغييرات؟ + إغلاق مسار الرحلة دون حفظ؟ ستفقد كل التغييرات؟ في حالة الاتجاه المعاكس تسجيل المسار أثناء الملاحة حفظ كملف مسار جديد @@ -3997,8 +3997,8 @@ \n • دعم ألوان مخصصة للمفضلة ونقاط لمسار الطريق \n \n - وضع الاستعراض - ملف تعريف المستخدم + وضع أساسي + وضع المستخدم عكس جميع النقاط حدد الوضع الذي سيتم استخدامه في بدء التطبيق. آخر استخدام @@ -4074,4 +4074,13 @@ رفع %1$d من %2$d تم رفع %1$d من %2$d تحديد التعديلات للتحميل + التضاريس / الانحدار / الخطوط المحيطية + OpenPlaceReviews هو مشروع يحركه المجتمع حول الأماكن العامة مثل المطاعم والفنادق والمتاحف ونقاط الطريق. يقوم بجمع جميع المعلومات العامة المتعلقة بهم مثل الصور والتعليقات والروابط إلى ارتباط الأنظمة الأخرى OpenStreetMap و Wikipedia. +\n +\nجميع بيانات OpenPlaceReview مفتوحة ومتاحة للجميع: http://openplacereviews.org/data. +\n +\nيمكنك قراءة المزيد على: http://openplacereviews.org + مراجعات الأمكنة + استخدام test.openplacereviews.org + الدخول إلى OpenPlaceReviews \ No newline at end of file diff --git a/OsmAnd/res/values-cs/phrases.xml b/OsmAnd/res/values-cs/phrases.xml index 8c6b4981ff..8fafe343d7 100644 --- a/OsmAnd/res/values-cs/phrases.xml +++ b/OsmAnd/res/values-cs/phrases.xml @@ -3601,7 +3601,7 @@ Přístup vozidel: vojenské Přístup vozidel: zásobování Přístup vozidel: lesnictví - Přístup aut: + Přístup aut: ano Přístup aut: soukromý Přístup aut: ne Přístup aut: cíl @@ -3835,4 +3835,50 @@ Neimigrační víza Konzulát Ambasáda + Mobilní směnárna + Prostředník + Prostředník + Netopýří tunel + Netopýří most + Ekodukt + Plovárna + Veřejná prádelna + Překladiště odpadů + Mostní váha + Stanice rangera + Jezero + Řeka + Studna + Poháněné čerpadlo + Vodní nádrž + Kohoutek + Zásobování vodou + Trubková studna + Očkování: COVID19 + Očkování + Záchranářská základna + Siréna + Zdravotní sestra + Ne + Ano + Ne + Ano + Ne + Ano + Podnárodní + Reprezentační kancelář + Kancelář + Honorární konzul + Generální konzulát + Kancelář konzula + Konzulární zastupitelstvo + Vedená konzulem + Rezidence + Nunciatura + Mise + Zájmová sekce + Vysoký komisař + Delegace + Pobočka + Vedená velvyslancem \ No newline at end of file diff --git a/OsmAnd/res/values-cs/strings.xml b/OsmAnd/res/values-cs/strings.xml index 738a4e98fe..ed36b49158 100644 --- a/OsmAnd/res/values-cs/strings.xml +++ b/OsmAnd/res/values-cs/strings.xml @@ -3425,7 +3425,7 @@ Směrové šipky Naposledy upraveno Importovat trasu - Otevřít existující trasu + Otevřít existující stopu Vytvořit novou trasu Vyberte stopu k otevření. Hotovo @@ -3442,10 +3442,10 @@ Přidat mezicíl Záznam trasy Uložit jako soubor trasy - Sledovat trasu + Sledovat stopu Zvolte soubor trasy, kterou chcete sledovat Zvolte soubor stopy, kterou chcete sledovat, nebo jej importujte ze svého zařízení. - Zvolit jinou trasu + Zvolit jinou stopu Navigovat z mé polohy k trase Bod trasy pro navigování Začátek trasy @@ -3490,7 +3490,7 @@ Ukládat trasu do GPX souboru Trasa ze stopy Přidat soubory stop - Zjednodušená trasa + Zjednodušená stopa Uloží se pouze linie trasy, mezicíle budou odstraněny. Název souboru %s vybraných souborů stop @@ -3505,7 +3505,7 @@ Pouze vybraný úsek bude přepočítán pomocí vybraného profilu. Všechny následující úseky budou přepočítány pomocí vybraného profilu. Všechny předcházející úseky budou přepočítány pomocí vybraného profilu. - Otevřít uloženou trasu + Otevřít uloženou stopu je uloženo Přidejte prosím alespoň dva body. Znovu @@ -3967,7 +3967,7 @@ Zvolte složku Zvolte složku nebo vytvořte novou Prázdné - Analyzovat podle intervalů (rozdělit interval) + Analyzovat rozdělené intervaly Nahrát do OpenStreetMap Editovat stopu Přejmenovat stopu @@ -4011,4 +4011,13 @@ Nahrávám %1$d z %2$d Nahráno %1$d z %2$d Vyberte úpravy pro nahrání + Stínované svahy / Sklon svahů / Vrstevnice + OpenPlaceReviews je komunitní projekt o veřejných místech, jako jsou restaurace, hotely, muzea a další. Shromažďuje o nich veškeré veřejné informace, např. fotografie, hodnocení, odkazy do dalších systémů jako OpenStreetMap či Wikipedie. +\n +\nVšechna data OpenPlaceReviews jsou otevřená a přístupná každému: http://openplacereviews.org/data. +\n +\nPřečtěte si více na http://openplacereviews.org + OpenPlaceReviews + Použít test.openplacereviews.org + Přihlásit se do OpenPlaceReviews \ No newline at end of file diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index f71ed65545..215d278648 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -3694,7 +3694,7 @@ Mapillary ein-/ausblenden Mapillary ausblenden Mapillary anzeigen - Eine Umschaltfläche zum ein- oder ausblenden der Mapillary-Layer auf der Karte. + Eine Umschaltfläche zum Ein- oder Ausblenden des Mapillary-Layers auf der Karte. Blitzer deinstallieren Rechtliches Blitzer-POIs @@ -4013,4 +4013,13 @@ Lade %1$d von %2$d hoch %1$d von %2$d hochgeladen Bearbeitungen zum Hochladen auswählen + Relief / Hangneigung / Höhenlinien + OpenPlaceReviews ist ein von der Gemeinschaft betriebenes Projekt über öffentliche Orte wie Restaurants, Hotels, Museen, Wegpunkte. Es sammelt alle öffentlichen Informationen über sie wie Fotos, Bewertungen, Links zu anderen Systemen, Link OpenStreetMap, Wikipedia. +\n +\nAlle OpenPlaceReview-Daten sind offen und für jedermann zugänglich: http://openplacereviews.org/data. +\n +\nMehr Informationen finden Sie unter: http://openplacereviews.org + OpenPlaceReviews + test.openplacereviews.org verwenden + Anmelden bei OpenPlaceReviews \ No newline at end of file diff --git a/OsmAnd/res/values-el/strings.xml b/OsmAnd/res/values-el/strings.xml index b1ddebc715..af31956d26 100644 --- a/OsmAnd/res/values-el/strings.xml +++ b/OsmAnd/res/values-el/strings.xml @@ -778,7 +778,7 @@ Ενημέρωση χάρτη Δημιουργία ΣΕ Ναι - Ακύρωση + Άκυρο Εφαρμογή Όχι Εισαγωγή ονόματος αγαπημένου @@ -1270,7 +1270,7 @@ Λήψη Νέου Χάρτη Γλώσσα χάρτη Μορφή δρόμου - Προκαθορισμένο + Προεπιλογή Πορτοκαλί Διασταύρωση σιδηροτροχιάς Διασταυρώσεις σιδηροτροχιάς @@ -1467,7 +1467,7 @@ Τμήματα διαδρομής Σημεία της διαδρομής Τοποθεσία:\n Γ. Πλ %1$s\n Γ. Μηκ %2$s - Προκαθορισμένο + Προεπιλογή Εκτύπωση διαδρομής εκπρόθεσμο Προσομοίωση της θέση σας @@ -3013,7 +3013,7 @@ Εμφάνιση στον χάρτη ζωνών για χαμηλή εκπομπή καυσαερίων. Δεν επηρεάζει τη δρομολόγηση. Εμφάνιση ζωνών χαμηλής εκπομπής καυσαερίων Λάβετε υπόψη τους προσωρινούς περιορισμούς - Προεπιλεγμένο + Προεπιλογή Ημιφορτηγό Ημέρα Ημέρες diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index 219a59ae10..da7a929cf2 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -654,7 +654,7 @@ Trovis nenion. Se vi ne povas trovi vian regionon, vi povas fari ĝin mem (rigardu https://osmand.net). Unue elektu GPX‑dosieron per frapetadi. Elektu kurson - Intertempo de divido + Fragmento Ordigi laŭ distanco Ordigi laŭ nomo Turisma map-vido @@ -2405,7 +2405,7 @@ Kontribui viajn strat-nivelajn vidaĵojn pri tiu ĉi loko al Mapillary. Strat-nivelaj fotoj por ĉiuj. Esplori lokojn, kunlabori kaj foti la mondon. Enretaj fotoj - Neniuj fotoj tie ĉi. + Neniu foto tie ĉi. Instali Pliigi fotan atingon de Mapillary Instalu la aplikaĵon Mapillary por aldoni fotojn al tiu ĉi loko sur la mapo. @@ -3967,7 +3967,7 @@ Elekti dosierujon Elekti dosierujon aŭ krei novan Malplena - Analizi laŭ intertempoj (dividoj) + Analizi laŭ fragmentoj Alŝuti al OpenStreetMap Redakti spuron Renomi spuron @@ -4011,4 +4011,13 @@ Sendado de %1$d el %2$d Sendis %1$d el %2$d Elektu redaktojn por sendi + Nivelombrumo / dekliveco / nivelkurboj + OpenPlaceReviews estas komunuma projekto pri publikaj lokoj, kiel restoracioj, hoteloj, muzeoj, rekoniloj, ktp. Ĝi kolektas diversajn publikajn informojn pri tiuj punktoj: fotojn, opiniojn, ligilojn al OpenStreetMap kaj Vikipedio. +\n +\nĈiuj OpenPlaceReview‑datumoj estas malfermaj kaj disponeblaj por ĉiu: http://openplacereviews.org/data +\n +\nPliaj informoj ĉe http://openplacereviews.org + OpenPlaceReviews + Uzi test.openplacereviews.org + Ensaluti al OpenPlaceReviews \ 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 ac7e14f5ee..44abab2a5b 100644 --- a/OsmAnd/res/values-es-rAR/phrases.xml +++ b/OsmAnd/res/values-es-rAR/phrases.xml @@ -2723,7 +2723,7 @@ Acuicultura: mejillones Edad mínima - No + Productos orgánicos: no Únicamente Espejo de tráfico Consulado diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index 18a479e18b..b1bdd574c8 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -772,24 +772,24 @@ \n Los PDI de OsmAnd están siendo desarrollados activamente. Nuestro proyecto y su continuo progreso, se basa en contribuciones económicas para desarrollar y probar nuevas funcionalidades. Por favor, considera comprar OsmAnd+, financiar nuevas funciones o hacer una donación general en https://osmand.net. Navegación y Mapas OsmAnd+ Visor y navegador móvil global de mapas OSM con y sin conexión - OsmAnd+ (OSM Automated Navigation Directions, y en español, Guía de Navegación Automatizada de OSM) -\n -\nOsmAnd+ es un software de navegación de código abierto con acceso a una amplia variedad de datos globales de OSM. Todos los datos del mapa (vectores y teselas), pueden ser almacenados en la memoria del teléfono para su uso sin conexión. Ofrece funcionalidades de rutas con y sin conexión, incluyendo guía de giro-a-giro por voz. -\n -\n OsmAnd+ es la versión de pago de la aplicación, comprándola ayudas al proyecto, financias el desarrollo de nuevas funciones, y recibes las últimas actualizaciones. -\n -\n Algunas de las funciones fundamentales: -\n - Completa funcionalidad sin conexión (guarda los mapas vectoriales o teselas descargados en el almacenamiento del dispositivo) -\n - Mapas mundiales vectoriales compactos disponibles -\n - Descarga ilimitada de mapas de países o regiones directamente desde la aplicación -\n - Posibilidad de superponer varias capas de mapa, como GPX o rutas de navegación, Puntos de Interés, Favoritos, curvas de nivel, paradas de transporte público, mapas adicionales con transparencia personalizable -\n -\n - Búsqueda sin conexión de direcciones y sitios (PDI) -\n - Rutas sin conexión para distancias de rango medio -\n - Modos de automóvil, bicicleta y peatón con opcional: -\n - Cambio automático de modo diurno/nocturno -\n - Zoom del mapa según la velocidad -\n - Alineación del mapa, según brújula o dirección del movimiento + OsmAnd+ (OSM Automated Navigation Directions, y en español, Guía de Navegación Automatizada de OSM) +\n +\n OsmAnd+ es un software de navegación de código abierto con acceso a una amplia variedad de datos globales de OSM. Todos los datos del mapa (vectores y teselas), pueden ser almacenados en la memoria del teléfono para su uso sin conexión. Ofrece funcionalidades de rutas con y sin conexión, incluyendo guía de giro-a-giro por voz. +\n +\n OsmAnd+ es la versión de pago de la aplicación, comprándola ayudas al proyecto, financias el desarrollo de nuevas funciones, y recibes las últimas actualizaciones. +\n +\n Algunas de las funciones fundamentales: +\n - Completa funcionalidad sin conexión (guarda los mapas vectoriales o teselas descargados en el almacenamiento del dispositivo) +\n - Mapas mundiales vectoriales compactos disponibles +\n - Descarga ilimitada de mapas de países o regiones directamente desde la aplicación +\n - Posibilidad de superponer varias capas de mapa, como GPX o rutas de navegación, Puntos de Interés, Favoritos, curvas de nivel, paradas de transporte público, mapas adicionales con transparencia personalizable +\n +\n - Búsqueda sin conexión de direcciones y sitios (PDI) +\n - Rutas sin conexión para distancias de rango medio +\n - Modos de automóvil, bicicleta y peatón con opcional: +\n - Cambio automático de modo diurno/nocturno +\n - Zoom del mapa según la velocidad +\n - Alineación del mapa, según brújula o dirección del movimiento \n - Indicación de carriles, mostrar límites de velocidad, voces grabadas y sintetizadas \n Crear filtro PDI @@ -1222,8 +1222,7 @@ Todos los datos sin conexión en la versión vieja de OsmAnd son compatibles con la nueva versión, pero los puntos de Favoritos deben exportarse desde la versión vieja y luego, importarse en la nueva. Compilación {0} instalada ({1}). Descargando compilación… - ¿Instalar OsmAnd? -\nVersión: {0} + ¿Instalar OsmAnd {0}\? \nFecha: {1} \nTamaño: {2} MB Error al recuperar la lista de compilaciones de OsmAnd @@ -2063,7 +2062,7 @@ Notificaciones Sin archivos de trazas aún También puedes añadir archivos de trazas a la carpeta - Añadir GPX + Añadir más… Aspecto Muy fino Cálculo de la ruta @@ -3732,8 +3731,8 @@ El punto añadido no será visible en el mapa, ya que el grupo elegido está oculto, se puede encontrar en «%s». Mostrar los iconos de inicio y fin Elegir la anchura - Marca el intervalo en el que se mostrarán las marcas con distancia o tiempo en la traza. - Marca la opción de división deseada: por tiempo o por distancia. + Elige el intervalo de la traza en el que se mostrarán las marcas con la distancia o el tiempo. + Elige la opción de división deseada: por tiempo o por distancia. Personalizado Flechas de dirección Sólido @@ -3970,7 +3969,7 @@ Elegir carpeta Elegir carpeta o añadir una nueva Vacío - Analizar por intervalos (intervalo de división) + Analizar intervalos divididos Subir a OpenStreetMap Editar traza Renombrar traza @@ -4014,4 +4013,13 @@ Subiendo %1$d de %2$d Se subieron %1$d de %2$d Marcar ediciones a subir + Sombreado / Pendiente / Curvas de nivel + OpenPlaceReviews es un proyecto impulsado por la comunidad sobre lugares públicos como restaurantes, hoteles, museos, puntos de referencia. Recoge toda la información pública sobre ellos como fotos, reseñas, enlaces a otros servicios como OpenStreetMap y Wikipedia. +\n +\nTodos los datos de OpenPlaceReviews son abiertos y están disponibles para todos: http://openplacereviews.org/data. +\n +\nPuedes leer más en: https://openplacereviews.org + OpenPlaceReviews + Usar test.openplacereviews.org + Acceder a OpenPlaceReviews \ No newline at end of file diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml index c963ab462e..1f8808c5dc 100644 --- a/OsmAnd/res/values-fr/strings.xml +++ b/OsmAnd/res/values-fr/strings.xml @@ -2382,7 +2382,7 @@ Enregistrer les traces dans des dossiers mensuels Enregistrer les traces dans des sous-dossiers organisés par mois (par exemple 2018-01). %1$d de %2$d - Durée de déplacement + Durée de mouvement Min / Max Rose translucide Suspendre / Reprendre la Navigation @@ -3981,7 +3981,7 @@ Ce nom existe déjà Poids lourd Durée - Analyser par intervalles (fractionner) + Analyser par intervalles de fractionnement Intervalles de temps et de distance Le délai d\'annonce des alertes vocales dépend du type d\'annonce, de la vitesse actuelle et du type de navigation. Délai de l\'annonce @@ -4001,4 +4001,8 @@ %1$d sur %2$d envoyé Envoi en cours Envoi terminé + Ombrage du relief / Pente / Courbes de niveaux + OpenPlaceReviews + Utilisez test.openplacereviews.org + Se connecter à OpenPlaceReviews \ No newline at end of file diff --git a/OsmAnd/res/values-gl/strings.xml b/OsmAnd/res/values-gl/strings.xml index c39329ec8e..6c078f0d5b 100644 --- a/OsmAnd/res/values-gl/strings.xml +++ b/OsmAnd/res/values-gl/strings.xml @@ -3998,4 +3998,35 @@ Lon %2$s Bicicleta de montaña Erro do servidor: %1$s O nome xa existe + Analizar intres divididos + Subir ao OpenStreetMap + Editar pista + Renomear pista + Mudar cartafol + seg + Pasando + Aproximación + Longa preparación + Preparar + Fóra da ruta + Eliminar este motor de navegación en liña\? + Ler completo + Editar descrición + Eliminar puntos de referencia + Copiar ás marcaxes do mapa + Copiar aos favoritos + Subindo + Subida completa + Subindo %1$d de %2$d + Subíronse %1$d de %2$d + Seleccionar edicións para subir + Sombras do relevo / Pendentes / Curvas de nivel + O OpenPlaceReviews é un proxecto impulsado pola comunidade sobre lugares públicos como restaurantes, hoteis, museos, puntos de referencia. Recolle toda a información pública sobre eles como imaxes, recesións, ligazóns a outros servizos como OpenStreetMap e Wikipedia. +\n +\nTodos os datos do OpenPlaceReviews son abertos e están dispoñíbeis para todos: http://openplacereviews.org/data. +\n +\nPodes ler máis en: https://openplacereviews.org + OpenPlaceReviews + Empregar test.openplacereviews.org + Iniciar sesión ao OpenPlaceReviews \ No newline at end of file diff --git a/OsmAnd/res/values-iw/strings.xml b/OsmAnd/res/values-iw/strings.xml index 737272e2e5..d91880e6d1 100644 --- a/OsmAnd/res/values-iw/strings.xml +++ b/OsmAnd/res/values-iw/strings.xml @@ -4013,4 +4013,7 @@ נשלחות %1$d מתוך %2$d נשלחו %1$d מתוך %2$d נא לבחור עריכות לשליחה + OpenPlaceReviews + להשתמש ב־test.openplacereviews.org + כניסה ל־OpenPlaceReviews \ 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 023809b5ae..afd52545aa 100644 --- a/OsmAnd/res/values-pt-rBR/strings.xml +++ b/OsmAnd/res/values-pt-rBR/strings.xml @@ -3782,7 +3782,7 @@ Alterar o tipo de rota antes Alterar o tipo de rota após Trilha simplificada - Apenas a linha da rota será salva, os waypoints serão excluídos. + Apenas a linha da rota será salva, os pontos de passagem serão excluídos. Nome do arquivo %s arquivos de trilha selecionados O registro de trilhas fará uma pausa quando o aplicativo for encerrado (por meio de aplicativos recentes). (A indicação de segundo plano do OsmAnd desaparece da barra de notificação do Android.) @@ -3962,7 +3962,7 @@ Selecione a pasta Selecione a pasta ou adicione uma nova Vazio - Analisar por intervalos (intervalo de divisão) + Analisar intervalos de divisão Carregar para OpenStreetMap Editar trilha Renomear trilha @@ -4006,4 +4006,5 @@ Carregando %1$d de %2$d Carregado %1$d de %2$d Selecione as edições para carregamento + Sombras de relevo / Encostas / Curvas de nível \ No newline at end of file diff --git a/OsmAnd/res/values-ru/phrases.xml b/OsmAnd/res/values-ru/phrases.xml index 839721ba13..95e72999d5 100644 --- a/OsmAnd/res/values-ru/phrases.xml +++ b/OsmAnd/res/values-ru/phrases.xml @@ -3878,4 +3878,5 @@ Станция перекачки отходов Станция рейнджеров Место для купания + Экодук \ No newline at end of file diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index 5747a78d85..4836ea274c 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -3992,4 +3992,13 @@ Отправка %1$d из %2$d Отправлено %1$d из %2$d Выберите правки для отправки + Рельеф / Уклон/ Контурные линии + Транспортное средство + Велосипед + Электрический велосипед + Горный велосипед + Шоссейный велосипед + Обычный велосипед + Гоночный велосипед + Горный велосипед \ No newline at end of file diff --git a/OsmAnd/res/values-sk/strings.xml b/OsmAnd/res/values-sk/strings.xml index 84b80a03a8..ada5be40c9 100644 --- a/OsmAnd/res/values-sk/strings.xml +++ b/OsmAnd/res/values-sk/strings.xml @@ -2415,7 +2415,7 @@ Vzdialenosť opravená Povolenia Nepodarilo sa naimportovať súbor. Prosím zabezpečte, že OsmAnd má oprávnenie čítať súbor. - Polomerové pravítko + Kruhové pravítko Resetovať Znovu načítať Znovu načítať dlaždice pre získanie aktuálnych dát. @@ -3580,7 +3580,7 @@ Stopovanie OsmAnd OsmAnd + Mapillary Rýchla akcia - Polomerové pravítko + Kruhové pravítko Merať vzdialenosť Cestovanie (Wikivoyage a Wikipédia) Mapové značky @@ -3962,7 +3962,7 @@ Zvoľte priečinok Zvoľte priečinok alebo pridajte nový Prázdne - Analyzovať podľa intervalov (rozdeliť interval) + Analyzovať rozdelené intervaly Nahrať do OpenStreetMap Upraviť stopu Premenovať stopu @@ -4006,4 +4006,5 @@ Odosiela sa %1$d z %2$d Odoslané %1$d z %2$d Zvoľte úpravy na odoslanie + Tieňované svahy / Sklony svahov / Vrstevnice \ No newline at end of file diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml index f724876c74..470ebc3850 100644 --- a/OsmAnd/res/values-uk/strings.xml +++ b/OsmAnd/res/values-uk/strings.xml @@ -2971,7 +2971,7 @@ Лижі Лижі Показати компас-лінійку - Приховати компас-лінійку + Сховати компас-лінійку Оберіть значок Режим: %s Користувацький режим, похідний від: %s @@ -2988,7 +2988,7 @@ Зберегти зміни Спочатку збережіть зміни в профілі Видалити профіль - Ви дійсно хочете видалити профіль %s\? + Ви дійсно хочете видалити профіль «%s» Виберіть профіль для початку Служба завантаження OsmAnd Пурпуровий @@ -3302,7 +3302,7 @@ Профілі, додані втулком Вимкнути Нова втулка додана - Приєднати частки + Об’єднати сегменти Додати новий профіль \'%1$s\'\? Зберегти заголовок Зберегти заголовок для кожної точки треку під час запису. @@ -3736,7 +3736,7 @@ Суцільний В останнє змінено Імпортувати трек - Переглянути наявний трек + Відкрити наявний трек Створити новий маршрут Виберіть який файл з треком відкрити. Готово @@ -3966,7 +3966,7 @@ Вибрати теку Виберіть теку або додайте нову Порожньо - Аналіз за інтервалами (розділений інтервал) + Аналізувати розділені інтервали Відвантажити на OpenStreetMap Редагувати трек Перейменувати трек @@ -4010,4 +4010,5 @@ Вивантаження %1$d з %2$d Вивантажено %1$d з %2$d Виберіть зміни для вивантаження + Рельєф місцевості / Схили / Горизонталі \ No newline at end of file diff --git a/OsmAnd/res/values-zh-rCN/strings.xml b/OsmAnd/res/values-zh-rCN/strings.xml index c21fc6f733..9550f1fb9c 100644 --- a/OsmAnd/res/values-zh-rCN/strings.xml +++ b/OsmAnd/res/values-zh-rCN/strings.xml @@ -35,7 +35,7 @@ 避開高速路 自动缩放地图 運輸方式: - 選擇傳輸模式 + 运输模式: 地图风格 熒光路線 統治者 @@ -430,9 +430,9 @@ 等高线数据 录制视频 录制音频 - 选择缺省窗体动作。 + 默认小部件操作: 缺省窗体动作 - 选择视频输出格式。 + 视频输出格式: 视频输出格式 使用系统程序录制视频。 使用系统程序拍照 @@ -481,7 +481,7 @@ 路线小地图 设置唤醒间隔: 上次导航未完成。是否继续?(%1$s 秒) - 选择模拟导航速度 + 路线模拟速度: 已分配内存 %1$s MB (Android 限制 %2$s MB,Dalvik %3$s MB)。 分享位置 有时间限制 @@ -555,7 +555,7 @@ 开始模拟导航 文件无法重命名。 同名文件已存在。 - 找到多个满足查询的POI类别: + 找到了几个相关的 POI 类别。 用于搜索POI的本地数据不存在。 按名称搜索 兴趣点数据文件 \'%1$s\' 是多余的,可以删除。 @@ -2020,7 +2020,7 @@ 感谢您使用 OsmAnd。对于此应用程序的许多功能,您需要一些地区的离线数据,您可以透过\'设置\' -> \'管理地图文件\'来下载。之后您可浏览地图、位置的地址、查看兴趣点以及寻找大众运输工具。 底图为某些特别的应用功能必需使用的,并且缺省为下载。 启动插件的高级设置和更多的附加功能。 - 用所选择的语音播放指令 + 通过播放通知选择语音和测试: 回到目前位置 横向(8 个扇区) 顺时针(12 个扇区) @@ -3068,7 +3068,7 @@ 到期时间 选择如何储存下载的数据。 你可以在应用配置中导入导出快捷操作。 - 你确定要删除%d快捷操作吗? + 你确定要不可撤销地删除 %d 快捷操作吗? 在某些国家或地区,使用测速摄像头提示应用是非法的。 \n \n你需要根据你所在的国家的法律作出选择。 diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml index 9b601f4c19..388b13d671 100644 --- a/OsmAnd/res/values-zh-rTW/strings.xml +++ b/OsmAnd/res/values-zh-rTW/strings.xml @@ -3960,7 +3960,7 @@ 選取資料夾 選取資料夾或新增 - 按時間間隔分析(分割時間間隔) + 分析分割間隔 上傳到 OpenStreetMap 編輯軌跡 重新命名軌跡 @@ -4004,4 +4004,5 @@ 正在上傳 %1$d,共 %2$d 已上傳 %1$d,共 %2$d 選取要上傳的檔案 + 地形陰影/斜坡/等高線 \ No newline at end of file diff --git a/OsmAnd/res/values/phrases.xml b/OsmAnd/res/values/phrases.xml index 13efca2404..5811de0322 100644 --- a/OsmAnd/res/values/phrases.xml +++ b/OsmAnd/res/values/phrases.xml @@ -4340,4 +4340,9 @@ Piste status: open Piste status: closed + Summit register: yes + Summit register: no + + Mobile library stop position + diff --git a/OsmAnd/src-gms/net/osmand/plus/LocationServiceHelperImpl.java b/OsmAnd/src-gms/net/osmand/plus/LocationServiceHelperImpl.java index 41c74012a3..eaab9e3d06 100644 --- a/OsmAnd/src-gms/net/osmand/plus/LocationServiceHelperImpl.java +++ b/OsmAnd/src-gms/net/osmand/plus/LocationServiceHelperImpl.java @@ -63,11 +63,11 @@ public class LocationServiceHelperImpl extends LocationServiceHelper { // Sets the fastest rate for active location updates. This interval is exact, and your // application will never receive updates more frequently than this value. - .setFastestInterval(50) + //.setFastestInterval(50) // Sets the maximum time when batched location updates are delivered. Updates may be // delivered sooner than this interval. - .setMaxWaitTime(200) + .setMaxWaitTime(0) .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); diff --git a/OsmAnd/src/net/osmand/plus/GpxDbHelper.java b/OsmAnd/src/net/osmand/plus/GpxDbHelper.java index c27c74f636..8a7d886a63 100644 --- a/OsmAnd/src/net/osmand/plus/GpxDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxDbHelper.java @@ -8,10 +8,10 @@ import androidx.annotation.Nullable; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; -import net.osmand.plus.track.GpxSplitType; import net.osmand.GPXUtilities.GPXTrackAnalysis; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; +import net.osmand.plus.track.GpxSplitType; import net.osmand.plus.track.GradientScaleType; import java.io.File; @@ -238,7 +238,7 @@ public class GpxDbHelper { gpxFile = readingItems.poll(); while (gpxFile != null && !isCancelled()) { GpxDataItem item = readingItemsMap.remove(gpxFile); - if (item.getFile() == null) { + if (item != null && item.getFile() == null) { item = db.getItem(gpxFile, conn); } if (isAnalyseNeeded(gpxFile, item)) { diff --git a/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java index e4f0c6fa58..88800d8fa0 100644 --- a/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java @@ -57,9 +57,6 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra private LinearLayout itemsContainer; private LinearLayout buttonsContainer; - @StringRes - protected int dismissButtonStringRes = R.string.shared_string_cancel; - public void setUsedOnMap(boolean usedOnMap) { this.usedOnMap = usedOnMap; } @@ -261,11 +258,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra @StringRes protected int getDismissButtonTextId() { - return dismissButtonStringRes; - } - - protected void setDismissButtonTextId(@StringRes int stringRes) { - dismissButtonStringRes = stringRes; + return R.string.shared_string_cancel; } protected int getDismissButtonHeight(){ diff --git a/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java b/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java index 1649e1ea1a..e49137c6e0 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java @@ -257,7 +257,7 @@ public class IntentHelper { if (intent.hasExtra(TrackMenuFragment.OPEN_TRACK_MENU)) { String path = intent.getStringExtra(TRACK_FILE_NAME); boolean currentRecording = intent.getBooleanExtra(CURRENT_RECORDING, false); - TrackMenuFragment.showInstance(mapActivity, path, currentRecording); + TrackMenuFragment.showInstance(mapActivity, path, currentRecording, null); mapActivity.setIntent(null); } } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java index 2ad2bb6ee4..51e7370da6 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java @@ -74,6 +74,7 @@ import net.osmand.plus.views.layers.POIMapLayer; import net.osmand.plus.views.layers.TransportStopsLayer; import net.osmand.plus.widgets.TextViewEx; import net.osmand.plus.widgets.tools.ClickableSpanTouchListener; +import net.osmand.plus.wikipedia.WikiArticleHelper; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; @@ -801,18 +802,98 @@ public class MenuBuilder { return ll; } - public View buildDescriptionRow(final View view, final String textPrefix, final String description, int textColor, - int textLinesLimit, boolean matchWidthDivider) { - OnClickListener clickListener = new OnClickListener() { + public View buildDescriptionRow(final View view, final String description) { + + final String descriptionLabel = app.getString(R.string.shared_string_description); + View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { - POIMapLayer.showDescriptionDialog(view.getContext(), app, description, textPrefix); + POIMapLayer.showHtmlDescriptionDialog(view.getContext(), app, description, descriptionLabel); } }; - return buildRow(view, null, null, textPrefix, description, textColor, - null, false, null, true, textLinesLimit, - false, false, false, clickListener, matchWidthDivider); + if (!isFirstRow()) { + buildRowDivider(view); + } + + LinearLayout baseView = new LinearLayout(view.getContext()); + baseView.setOrientation(LinearLayout.VERTICAL); + LinearLayout.LayoutParams llBaseViewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + baseView.setLayoutParams(llBaseViewParams); + + LinearLayout ll = new LinearLayout(view.getContext()); + ll.setOrientation(LinearLayout.HORIZONTAL); + LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + ll.setLayoutParams(llParams); + ll.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + ll.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(description, view.getContext()); + return true; + } + }); + + baseView.addView(ll); + + // Text + LinearLayout llText = new LinearLayout(view.getContext()); + llText.setOrientation(LinearLayout.VERTICAL); + LinearLayout.LayoutParams llTextViewParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT); + llTextViewParams.weight = 1f; + AndroidUtils.setMargins(llTextViewParams, 0, 0, dpToPx(10f), 0); + llTextViewParams.gravity = Gravity.CENTER_VERTICAL; + llText.setLayoutParams(llTextViewParams); + ll.addView(llText); + + // Description label + TextViewEx textPrefixView = new TextViewEx(view.getContext()); + LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + AndroidUtils.setMargins(llTextParams, dpToPx(16f), dpToPx(8f), 0, 0); + textPrefixView.setLayoutParams(llTextParams); + textPrefixView.setTypeface(FontCache.getRobotoRegular(view.getContext())); + textPrefixView.setTextSize(12); + textPrefixView.setTextColor(app.getResources().getColor(light ? R.color.text_color_secondary_light : R.color.text_color_secondary_dark)); + textPrefixView.setMinLines(1); + textPrefixView.setMaxLines(1); + textPrefixView.setText(descriptionLabel); + llText.addView(textPrefixView); + + // Description + TextViewEx textView = new TextViewEx(view.getContext()); + LinearLayout.LayoutParams llDescriptionParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + AndroidUtils.setMargins(llDescriptionParams, dpToPx(16f), dpToPx(2f), 0, dpToPx(8f)); + textView.setLayoutParams(llDescriptionParams); + textView.setTypeface(FontCache.getRobotoRegular(view.getContext())); + textView.setTextSize(16); + textView.setTextColor(app.getResources().getColor(light ? R.color.text_color_primary_light : R.color.text_color_primary_dark)); + textView.setText(WikiArticleHelper.getPartialContent(description)); + + if (Linkify.addLinks(textView, Linkify.ALL)) { + textView.setMovementMethod(null); + int linkTextColor = ContextCompat.getColor(view.getContext(), light ? + R.color.ctx_menu_bottom_view_url_color_light : R.color.ctx_menu_bottom_view_url_color_dark); + textView.setLinkTextColor(linkTextColor); + textView.setOnTouchListener(new ClickableSpanTouchListener()); + AndroidUtils.removeLinkUnderline(textView); + } + textView.setMinLines(1); + textView.setMaxLines(10); + textView.setEllipsize(TextUtils.TruncateAt.END); + llText.addView(textView); + + // Read Full button + buildReadFullButton(llText, app.getString(R.string.context_menu_read_full), onClickListener); + + if (onClickListener != null) { + ll.setOnClickListener(onClickListener); + } + ((LinearLayout) view).addView(baseView); + + rowBuilt(); + setDividerWidth(true); + + return ll; } protected void showDialog(String text, final String actionType, final String dataPrefix, final View v) { @@ -908,6 +989,38 @@ public class MenuBuilder { ((LinearLayout) view).addView(horizontalLine); } + protected void buildReadFullButton(LinearLayout container, String btnText, View.OnClickListener onClickListener) { + Context ctx = container.getContext(); + + TextViewEx button = new TextViewEx(new ContextThemeWrapper(ctx, light ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme)); + LinearLayout.LayoutParams llButtonParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, dpToPx(36f)); + AndroidUtils.setMargins(llButtonParams, dpToPx(16f), 0, 0, dpToPx(16f)); + button.setLayoutParams(llButtonParams); + button.setTypeface(FontCache.getRobotoMedium(app)); + button.setBackgroundResource(light ? R.drawable.context_menu_controller_bg_light : R.drawable.context_menu_controller_bg_dark); + button.setTextSize(14); + int paddingSides = dpToPx(10f); + button.setPadding(paddingSides, 0, paddingSides, 0); + ColorStateList buttonColorStateList = AndroidUtils.createPressedColorStateList(ctx, !light, + R.color.ctx_menu_controller_button_text_color_light_n, R.color.ctx_menu_controller_button_text_color_light_p, + R.color.ctx_menu_controller_button_text_color_dark_n, R.color.ctx_menu_controller_button_text_color_dark_p); + button.setTextColor(buttonColorStateList); + button.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + button.setSingleLine(true); + button.setEllipsize(TextUtils.TruncateAt.END); + button.setOnClickListener(onClickListener); + button.setAllCaps(true); + button.setText(btnText); + Drawable normal = app.getUIUtilities().getIcon(R.drawable.ic_action_read_text, + light ? R.color.ctx_menu_controller_button_text_color_light_n : R.color.ctx_menu_controller_button_text_color_dark_n); + Drawable pressed = app.getUIUtilities().getIcon(R.drawable.ic_action_read_text, + light ? R.color.ctx_menu_controller_button_text_color_light_p : R.color.ctx_menu_controller_button_text_color_dark_p); + AndroidUtils.setCompoundDrawablesWithIntrinsicBounds(button, Build.VERSION.SDK_INT >= 21 + ? AndroidUtils.createPressedStateListDrawable(normal, pressed) : normal, null, null, null); + button.setCompoundDrawablePadding(dpToPx(8f)); + container.addView(button); + } + public boolean hasCustomAddressLine() { return false; } @@ -1144,7 +1257,9 @@ public class MenuBuilder { controller.setOnBackButtonClickListener(new OnClickListener() { @Override public void onClick(View v) { - mapContextMenu.show(); + if (mapContextMenu != null) { + mapContextMenu.show(); + } } }); controller.setOnTitleClickListener(new OnClickListener() { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java index 54e04071fa..846c2cdd0e 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java @@ -2,10 +2,8 @@ package net.osmand.plus.mapcontextmenu.builders; import android.content.Context; import android.content.Intent; -import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.os.Build; import android.text.TextUtils; import android.text.util.Linkify; import android.view.Gravity; @@ -15,10 +13,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.appcompat.view.ContextThemeWrapper; -import androidx.core.content.ContextCompat; - import net.osmand.AndroidUtils; import net.osmand.PlatformUtil; import net.osmand.data.Amenity; @@ -31,7 +25,6 @@ import net.osmand.plus.OsmandPlugin; 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; @@ -67,6 +60,9 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + public class AmenityMenuBuilder extends MenuBuilder { private static final String WIKI_LINK = ".wikipedia.org/w"; @@ -259,38 +255,12 @@ public class AmenityMenuBuilder extends MenuBuilder { } if (isWiki) { - TextViewEx button = new TextViewEx(new ContextThemeWrapper(view.getContext(), light ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme)); - LinearLayout.LayoutParams llWikiButtonParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, dpToPx(36f)); - AndroidUtils.setMargins(llWikiButtonParams, dpToPx(16f), 0, 0, dpToPx(16f)); - button.setLayoutParams(llWikiButtonParams); - button.setTypeface(FontCache.getRobotoMedium(app)); - button.setBackgroundResource(light ? R.drawable.context_menu_controller_bg_light : R.drawable.context_menu_controller_bg_dark); - button.setTextSize(14); - int paddingSides = dpToPx(10f); - button.setPadding(paddingSides, 0, paddingSides, 0); - ColorStateList buttonColorStateList = AndroidUtils.createPressedColorStateList(view.getContext(), !light, - R.color.ctx_menu_controller_button_text_color_light_n, R.color.ctx_menu_controller_button_text_color_light_p, - R.color.ctx_menu_controller_button_text_color_dark_n, R.color.ctx_menu_controller_button_text_color_dark_p); - button.setTextColor(buttonColorStateList); - button.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); - button.setSingleLine(true); - button.setEllipsize(TextUtils.TruncateAt.END); - button.setOnClickListener(new View.OnClickListener() { + buildReadFullButton(llText, app.getString(R.string.context_menu_read_full_article), new View.OnClickListener() { @Override public void onClick(View view) { WikipediaDialogFragment.showInstance(mapActivity, amenity); } }); - button.setAllCaps(true); - button.setText(R.string.context_menu_read_full_article); - Drawable normal = app.getUIUtilities().getIcon(R.drawable.ic_action_read_text, - light ? R.color.ctx_menu_controller_button_text_color_light_n : R.color.ctx_menu_controller_button_text_color_dark_n); - Drawable pressed = app.getUIUtilities().getIcon(R.drawable.ic_action_read_text, - light ? R.color.ctx_menu_controller_button_text_color_light_p : R.color.ctx_menu_controller_button_text_color_dark_p); - AndroidUtils.setCompoundDrawablesWithIntrinsicBounds(button, Build.VERSION.SDK_INT >= 21 - ? AndroidUtils.createPressedStateListDrawable(normal, pressed) : normal, null, null, null); - button.setCompoundDrawablePadding(dpToPx(8f)); - llText.addView(button); } ((LinearLayout) view).addView(baseView); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/FavouritePointMenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/FavouritePointMenuBuilder.java index ca404569b1..113ff5c12e 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/FavouritePointMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/FavouritePointMenuBuilder.java @@ -4,8 +4,6 @@ import android.content.Context; import android.view.View; import android.widget.LinearLayout; -import androidx.annotation.NonNull; - import net.osmand.PlatformUtil; import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapIndexReader; @@ -19,8 +17,8 @@ import net.osmand.osm.PoiCategory; import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.CollapsableView; +import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.myplaces.FavoritesActivity; import net.osmand.plus.widgets.TextViewEx; import net.osmand.util.Algorithms; @@ -29,6 +27,8 @@ import net.osmand.util.MapUtils; import java.io.IOException; import java.util.List; +import androidx.annotation.NonNull; + public class FavouritePointMenuBuilder extends MenuBuilder { private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(FavouritePointMenuBuilder.class); @@ -85,7 +85,7 @@ public class FavouritePointMenuBuilder extends MenuBuilder { protected void buildDescription(View view) { String desc = fav.getDescription(); if (!Algorithms.isEmpty(desc)) { - buildDescriptionRow(view, app.getString(R.string.shared_string_description), desc, 0, 10, true); + buildDescriptionRow(view, desc); } } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/WptPtMenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/WptPtMenuBuilder.java index c6a287f86b..278e0cd432 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/WptPtMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/WptPtMenuBuilder.java @@ -4,10 +4,6 @@ import android.content.Context; import android.view.View; import android.widget.LinearLayout; -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; - import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.WptPt; import net.osmand.IndexConstants; @@ -30,6 +26,10 @@ import java.text.DateFormat; import java.util.Date; import java.util.List; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + public class WptPtMenuBuilder extends MenuBuilder { private final WptPt wpt; @@ -52,10 +52,22 @@ public class WptPtMenuBuilder extends MenuBuilder { } @Override - protected void buildDescription(View view) { - if (!Algorithms.isEmpty(wpt.desc)) { - buildDescriptionRow(view, app.getString(R.string.shared_string_description), wpt.desc, 0, 10, true); + protected void buildDescription(final View view) { + if (Algorithms.isEmpty(wpt.desc)) { + return; } + + final String textPrefix = app.getString(R.string.shared_string_description); + View.OnClickListener clickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + POIMapLayer.showDescriptionDialog(view.getContext(), app, wpt.desc, textPrefix); + } + }; + + buildRow(view, null, null, textPrefix, wpt.desc, 0, + null, false, null, true, 10, + false, false, false, clickListener, matchWidthDivider); } @Override diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java index 6e062829a6..1128eb0531 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java @@ -45,7 +45,9 @@ public class SelectedGpxMenuController extends MenuController { mapContextMenu.hide(false); WptPt wptPt = selectedGpxPoint.selectedPoint; LatLon latLon = new LatLon(wptPt.lat, wptPt.lon); - TrackMenuFragment.showInstance(mapActivity, selectedGpxPoint.getSelectedGpxFile(), latLon); + SelectedGpxFile selectedGpxFile = selectedGpxPoint.getSelectedGpxFile(); + String path = selectedGpxFile.getGpxFile().path; + TrackMenuFragment.showInstance(mapActivity, path, selectedGpxFile.isShowCurrentTrack(), latLon); } }; leftTitleButtonController.caption = mapActivity.getString(R.string.shared_string_open_track); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/WptPtMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/WptPtMenuController.java index f436fb03fb..0ac1cc5437 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/WptPtMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/WptPtMenuController.java @@ -1,6 +1,7 @@ package net.osmand.plus.mapcontextmenu.controllers; import android.graphics.drawable.Drawable; +import android.util.Pair; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; @@ -11,25 +12,27 @@ import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; -import net.osmand.plus.mapmarkers.MapMarkersHelper; -import net.osmand.plus.mapmarkers.MapMarker; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.PointImageDrawable; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.MenuController; +import net.osmand.plus.mapmarkers.MapMarker; +import net.osmand.plus.mapmarkers.MapMarkersHelper; +import net.osmand.plus.track.TrackMenuFragment; import net.osmand.plus.wikivoyage.menu.WikivoyageWptPtMenuBuilder; -import net.osmand.plus.wikivoyage.menu.WikivoyageWptPtMenuController; import net.osmand.util.Algorithms; import java.io.File; +import java.util.ArrayList; public class WptPtMenuController extends MenuController { private WptPt wpt; private MapMarker mapMarker; - public WptPtMenuController(@NonNull MenuBuilder menuBuilder, @NonNull MapActivity mapActivity, @NonNull PointDescription pointDescription, @NonNull final WptPt wpt) { + public WptPtMenuController(@NonNull MenuBuilder menuBuilder, @NonNull MapActivity mapActivity, + @NonNull PointDescription pointDescription, @NonNull final WptPt wpt) { super(menuBuilder, pointDescription, mapActivity); this.wpt = wpt; MapMarkersHelper markersHelper = mapActivity.getMyApplication().getMapMarkersHelper(); @@ -37,11 +40,34 @@ public class WptPtMenuController extends MenuController { if (mapMarker == null) { mapMarker = markersHelper.getMapMarker(new LatLon(wpt.lat, wpt.lon)); } + + TitleButtonController openTrackButtonController = new TitleButtonController() { + @Override + public void buttonPressed() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + GpxSelectionHelper selectionHelper = mapActivity.getMyApplication().getSelectedGpxHelper(); + SelectedGpxFile selectedGpxFile = selectionHelper.getSelectedGPXFile(wpt); + if (selectedGpxFile != null) { + String path = selectedGpxFile.getGpxFile().path; + TrackMenuFragment.showInstance(mapActivity, path, selectedGpxFile.isShowCurrentTrack(), new LatLon(wpt.lon, wpt.lat)); + } + } + } + }; + openTrackButtonController.startIconId = R.drawable.ic_action_polygom_dark; + openTrackButtonController.caption = mapActivity.getString(R.string.shared_string_open_track); + if (mapMarker != null) { - MapMarkerMenuController markerMenuController = - new MapMarkerMenuController(mapActivity, mapMarker.getPointDescription(mapActivity), mapMarker); + PointDescription description = mapMarker.getPointDescription(mapActivity); + MapMarkerMenuController markerMenuController = new MapMarkerMenuController(mapActivity, description, mapMarker); leftTitleButtonController = markerMenuController.getLeftTitleButtonController(); rightTitleButtonController = markerMenuController.getRightTitleButtonController(); + + additionalButtonsControllers = new ArrayList<>(); + additionalButtonsControllers.add(Pair.create(openTrackButtonController, null)); + } else { + leftTitleButtonController = openTrackButtonController; } } @@ -143,10 +169,6 @@ public class WptPtMenuController extends MenuController { } public static WptPtMenuController getInstance(@NonNull MapActivity mapActivity, @NonNull PointDescription pointDescription, @NonNull final WptPt wpt) { - WptPtMenuController controller = WikivoyageWptPtMenuController.getInstance(mapActivity, pointDescription, wpt); - if (controller == null) { - controller = new WptPtMenuController(new WikivoyageWptPtMenuBuilder(mapActivity, wpt), mapActivity, pointDescription, wpt); - } - return controller; + return new WptPtMenuController(new WikivoyageWptPtMenuBuilder(mapActivity, wpt), mapActivity, pointDescription, wpt); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHelper.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHelper.java index fac88b2069..51911e8779 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHelper.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHelper.java @@ -1236,11 +1236,10 @@ public class MapMarkersHelper { removeGroupActiveMarkers(group, true); return; } - for (FavouritePoint fp : favGroup.getPoints()) { + List points = new ArrayList<>(favGroup.getPoints()); + for (FavouritePoint fp : points) { addNewMarkerIfNeeded(group, groupMarkers, new LatLon(fp.getLatitude(), fp.getLongitude()), fp.getName(), fp, null); } - - } else if (group.getType() == MapMarkersGroup.GPX_TYPE) { GpxSelectionHelper gpxHelper = ctx.getSelectedGpxHelper(); File file = new File(group.getId()); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SaveGpxRouteAsyncTask.java b/OsmAnd/src/net/osmand/plus/measurementtool/SaveGpxRouteAsyncTask.java index ea85fe9fdd..8bf1c80b2f 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SaveGpxRouteAsyncTask.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SaveGpxRouteAsyncTask.java @@ -10,11 +10,11 @@ import net.osmand.AndroidUtils; import net.osmand.FileUtils; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; +import net.osmand.GPXUtilities.Metadata; import net.osmand.GPXUtilities.Route; import net.osmand.GPXUtilities.Track; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; -import net.osmand.GPXUtilities.Metadata; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.Version; @@ -104,6 +104,10 @@ class SaveGpxRouteAsyncTask extends AsyncTask { MeasurementToolFragment.showGpxOnMap(app, gpx, false); } } + if (res == null) { + savedGpxFile.addGeneralTrack(); + } + return res; } diff --git a/OsmAnd/src/net/osmand/plus/monitoring/SaveGPXBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/monitoring/SaveGPXBottomSheetFragment.java index 4bd5e6bcda..d37d113e6c 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/SaveGPXBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/SaveGPXBottomSheetFragment.java @@ -143,6 +143,12 @@ public class SaveGPXBottomSheetFragment extends MenuBottomSheetDialogFragment { return UiUtilities.DialogButtonType.SECONDARY; } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_close; + } + @Override protected int getRightBottomButtonTextId() { return R.string.shared_string_open_track; diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java index 55b24b7ed4..946d79ca18 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java @@ -542,6 +542,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { mapActivity.getContextMenu().showOrUpdate( new LatLon(point.getLatitude(), point.getLongitude()), plugin.getOsmEditsLayer(mapActivity).getObjectName(point), point); + mapActivity.getMapLayers().getContextMenuLayer().updateContextMenu(); } } @@ -869,6 +870,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { mapActivity.getContextMenu().showOrUpdate( new LatLon(point.getLatitude(), point.getLongitude()), plugin.getOsmEditsLayer(mapActivity).getObjectName(point), point); + mapActivity.getMapLayers().getContextMenuLayer().updateContextMenu(); } } else { Toast.makeText(activity, R.string.poi_remove_success, Toast.LENGTH_LONG) diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsLayer.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsLayer.java index a13ae28bba..c4ab750fb3 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsLayer.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsLayer.java @@ -387,6 +387,7 @@ public class OsmBugsLayer extends OsmandMapLayer implements IContextMenuProvider PointDescription pd = new PointDescription(PointDescription.POINT_TYPE_OSM_BUG, obj.local.getText()); activity.getContextMenu().show(new LatLon(obj.local.getLatitude(), obj.local.getLongitude()), pd, obj.local); + activity.getMapLayers().getContextMenuLayer().updateContextMenu(); } } else { if (action == Action.REOPEN) { diff --git a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java index 0c6c586bc4..406642c155 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java @@ -7,6 +7,7 @@ import android.os.AsyncTask; import android.view.ViewGroup; import com.github.scribejava.core.builder.api.DefaultApi10a; +import com.github.scribejava.core.exceptions.OAuthException; import com.github.scribejava.core.model.OAuth1AccessToken; import com.github.scribejava.core.model.OAuth1RequestToken; import com.github.scribejava.core.model.OAuthAsyncRequestCallback; @@ -171,6 +172,8 @@ public class OsmOAuthAuthorizationAdapter { log.error(e); } catch (XmlPullParserException e) { log.error(e); + } catch (OAuthException e) { + log.error(e); } app.getSettings().OSM_USER_DISPLAY_NAME.set(userName); } diff --git a/OsmAnd/src/net/osmand/plus/profiles/AppModesBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/profiles/AppModesBottomSheetDialogFragment.java index 8b61d67462..70356e9945 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/AppModesBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/profiles/AppModesBottomSheetDialogFragment.java @@ -27,10 +27,14 @@ public abstract class AppModesBottomSheetDialogFragment items = new ArrayList<>(); + + prepareData(analysis, items, app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app), + R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED, ItemType.ITEM_DISTANCE); + prepareData(analysis, items, app.getString(R.string.altitude_ascent), asc, + R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ItemType.ITEM_ALTITUDE); + prepareData(analysis, items, app.getString(R.string.altitude_descent), desc, + R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ItemType.ITEM_ALTITUDE); + prepareData(analysis, items, app.getString(R.string.average_speed), avg, + R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED); + prepareData(analysis, items, app.getString(R.string.max_speed), max, + R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED); + prepareData(analysis, items, app.getString(R.string.shared_string_time_span), + Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()), + R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME); + + if (Algorithms.isEmpty(items)) { + AndroidUiHelper.updateVisibility(blocksView, false); + } else { + final BlockStatisticsAdapter sbAdapter = new BlockStatisticsAdapter(items, actionsListener, activeColor, nightMode); + blocksView.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false)); + blocksView.setAdapter(sbAdapter); + } + } + + public void prepareData(GPXTrackAnalysis analysis, List listItems, String title, + String value, @DrawableRes int imageResId, @ColorRes int imageColorId, + GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) { + StatBlock statBlock = new StatBlock(title, value, imageResId, imageColorId, firstType, secondType, itemType); + switch (statBlock.itemType) { + case ITEM_DISTANCE: { + if (analysis.totalDistance != 0f) { + listItems.add(statBlock); + } + break; + } + case ITEM_ALTITUDE: { + if (analysis.hasElevationData) { + listItems.add(statBlock); + } + break; + } + case ITEM_SPEED: { + if (analysis.isSpeedSpecified()) { + listItems.add(statBlock); + } + break; + } + case ITEM_TIME: { + if (analysis.hasSpeedData) { + listItems.add(statBlock); + } + break; + } + } + } + + private void setImageDrawable(ImageView iv, @DrawableRes Integer resId, @ColorRes int color) { + Drawable icon = resId != null ? app.getUIUtilities().getIcon(resId, color) + : UiUtilities.tintDrawable(iv.getDrawable(), getResolvedColor(color)); + iv.setImageDrawable(icon); + } + + @ColorInt + protected int getResolvedColor(@ColorRes int colorId) { + return ContextCompat.getColor(app, colorId); + } + + public class StatBlock { + + private final String title; + private final String value; + private final int imageResId; + private final int imageColorId; + private final GPXDataSetType firstType; + private final GPXDataSetType secondType; + private final ItemType itemType; + + public StatBlock(String title, String value, @DrawableRes int imageResId, @ColorRes int imageColorId, + GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) { + this.title = title; + this.value = value; + this.imageResId = imageResId; + this.imageColorId = imageColorId; + this.firstType = firstType; + this.secondType = secondType; + this.itemType = itemType; + } + } + + public enum ItemType { + ITEM_DISTANCE, + ITEM_ALTITUDE, + ITEM_SPEED, + ITEM_TIME; + } + + private class BlockStatisticsAdapter extends RecyclerView.Adapter { + + @ColorInt + private final int activeColor; + private final List statBlocks; + private final boolean nightMode; + private final SegmentActionsListener actionsListener; + + public BlockStatisticsAdapter(List statBlocks, SegmentActionsListener actionsListener, @ColorInt int activeColor, boolean nightMode) { + this.statBlocks = statBlocks; + this.actionsListener = actionsListener; + this.activeColor = activeColor; + this.nightMode = nightMode; + } + + @Override + public int getItemCount() { + return statBlocks.size(); + } + + @NonNull + @Override + public BlockStatisticsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_gpx_stat_block, parent, false); + return new BlockStatisticsViewHolder(itemView); + } + + @Override + public void onBindViewHolder(BlockStatisticsViewHolder holder, int position) { + final StatBlock item = statBlocks.get(position); + holder.valueText.setText(item.value); + holder.titleText.setText(item.title); + holder.valueText.setTextColor(activeColor); + holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light)); + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + List groups = displayHelper.getDisplayGroups(filterTypes); + GpxDisplayGroup group = null; + for (GpxDisplayGroup g : groups) { + if (g.isGeneralTrack()) { + group = g; + } + } + if (group == null && !groups.isEmpty()) { + group = groups.get(0); + } + if (group != null) { + GpxDisplayItem displayItem = group.getModifiableList().get(0); + if (displayItem != null && displayItem.analysis != null) { + ArrayList list = new ArrayList<>(); + if (displayItem.analysis.hasElevationData || displayItem.analysis.isSpeedSpecified() || displayItem.analysis.hasSpeedData) { + if (item.firstType != null) { + list.add(item.firstType); + } + if (item.secondType != null) { + list.add(item.secondType); + } + } + displayItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null; + displayItem.locationOnMap = displayItem.locationStart; + actionsListener.openAnalyzeOnMap(displayItem); + } + } + } + }); + setImageDrawable(holder.imageView, item.imageResId, item.imageColorId); + AndroidUtils.setBackgroundColor(app, holder.divider, nightMode, R.color.divider_color_light, R.color.divider_color_dark); + AndroidUiHelper.updateVisibility(holder.divider, position != statBlocks.size() - 1); + } + } + + private class BlockStatisticsViewHolder extends RecyclerView.ViewHolder { + + private final TextViewEx valueText; + private final TextView titleText; + private final AppCompatImageView imageView; + private final View divider; + + public BlockStatisticsViewHolder(View view) { + super(view); + valueText = view.findViewById(R.id.value); + titleText = view.findViewById(R.id.title); + imageView = view.findViewById(R.id.image); + divider = view.findViewById(R.id.divider); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/track/OverviewCard.java b/OsmAnd/src/net/osmand/plus/track/OverviewCard.java index e43b6d139f..5d46a69c25 100644 --- a/OsmAnd/src/net/osmand/plus/track/OverviewCard.java +++ b/OsmAnd/src/net/osmand/plus/track/OverviewCard.java @@ -2,73 +2,46 @@ package net.osmand.plus.track; import android.annotation.SuppressLint; import android.graphics.drawable.Drawable; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.TextView; import androidx.annotation.ColorRes; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.appcompat.widget.AppCompatImageView; -import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import net.osmand.AndroidUtils; import net.osmand.GPXUtilities.GPXFile; -import net.osmand.GPXUtilities.GPXTrackAnalysis; -import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; -import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; -import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; -import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.helpers.AndroidUiHelper; -import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.myplaces.SegmentActionsListener; import net.osmand.plus.routepreparationmenu.cards.BaseCard; -import net.osmand.plus.widgets.TextViewEx; -import net.osmand.util.Algorithms; - -import java.util.ArrayList; -import java.util.List; import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected; import static net.osmand.plus.track.OptionsCard.APPEARANCE_BUTTON_INDEX; import static net.osmand.plus.track.OptionsCard.DIRECTIONS_BUTTON_INDEX; import static net.osmand.plus.track.OptionsCard.EDIT_BUTTON_INDEX; import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX; -import static net.osmand.plus.track.OverviewCard.StatBlock.ItemType.*; public class OverviewCard extends BaseCard { - private RecyclerView rvOverview; private View showButton; private View appearanceButton; private View editButton; private View directionsButton; - - private final TrackDisplayHelper displayHelper; - private final GPXFile gpxFile; - private final GpxDisplayItemType[] filterTypes = {GpxDisplayItemType.TRACK_SEGMENT}; - private final SegmentActionsListener listener; - private boolean gpxFileSelected; - private GpxDisplayItem gpxItem; + private final SegmentActionsListener actionsListener; + private final SelectedGpxFile selectedGpxFile; + private final GpxBlockStatisticsBuilder blockStatisticsBuilder; public OverviewCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper, - @NonNull SegmentActionsListener listener) { + @NonNull SegmentActionsListener actionsListener, SelectedGpxFile selectedGpxFile) { super(mapActivity); - this.displayHelper = displayHelper; - this.listener = listener; - gpxFile = displayHelper.getGpx(); - gpxFileSelected = isGpxFileSelected(app, gpxFile); - List groups = displayHelper.getOriginalGroups(filterTypes); - if (!Algorithms.isEmpty(groups)) { - gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0); - } + this.actionsListener = actionsListener; + this.selectedGpxFile = selectedGpxFile; + blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile, displayHelper); } @Override @@ -80,13 +53,15 @@ public class OverviewCard extends BaseCard { protected void updateContent() { int iconColorDef = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; int iconColorPres = R.color.active_buttons_and_links_text_dark; + GPXFile gpxFile = getGPXFile(); boolean fileAvailable = gpxFile.path != null && !gpxFile.showCurrentTrack; showButton = view.findViewById(R.id.show_button); appearanceButton = view.findViewById(R.id.appearance_button); editButton = view.findViewById(R.id.edit_button); directionsButton = view.findViewById(R.id.directions_button); - rvOverview = view.findViewById(R.id.recycler_overview); + RecyclerView blocksView = view.findViewById(R.id.recycler_overview); + blockStatisticsBuilder.setBlocksView(blocksView); initShowButton(iconColorDef, iconColorPres); initAppearanceButton(iconColorDef, iconColorPres); @@ -94,51 +69,16 @@ public class OverviewCard extends BaseCard { initEditButton(iconColorDef, iconColorPres); initDirectionsButton(iconColorDef, iconColorPres); } - initStatBlocks(); + blockStatisticsBuilder.initStatBlocks(actionsListener, getActiveColor(), nightMode); } - void initStatBlocks() { - if (gpxItem != null) { - GPXTrackAnalysis analysis = gpxItem.analysis; - boolean joinSegments = displayHelper.isJoinSegments(); - float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance; - float timeSpan = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeSpanWithoutGaps : analysis.timeSpan; - String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app); - String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app); - String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app); - String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app); - List items = new ArrayList<>(); - - StatBlock.prepareData(analysis, items, app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app), - R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED, ITEM_DISTANCE); - StatBlock.prepareData(analysis, items, app.getString(R.string.altitude_ascent), asc, - R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ITEM_ALTITUDE); - StatBlock.prepareData(analysis, items, app.getString(R.string.altitude_descent), desc, - R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ITEM_ALTITUDE); - StatBlock.prepareData(analysis, items, app.getString(R.string.average_speed), avg, - R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_SPEED); - StatBlock.prepareData(analysis, items, app.getString(R.string.max_speed), max, - R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_SPEED); - StatBlock.prepareData(analysis, items, app.getString(R.string.shared_string_time_span), - Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()), - R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_TIME); - - if (Algorithms.isEmpty(items)) { - AndroidUiHelper.updateVisibility(rvOverview, false); - } else { - final StatBlockAdapter sbAdapter = new StatBlockAdapter(items); - rvOverview.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false)); - rvOverview.setAdapter(sbAdapter); - } - } else { - AndroidUiHelper.updateVisibility(rvOverview, false); - } + private GPXFile getGPXFile() { + return selectedGpxFile.getGpxFile(); } @DrawableRes private int getActiveShowHideIcon() { - gpxFileSelected = isGpxFileSelected(app, gpxFile); - return gpxFileSelected ? R.drawable.ic_action_view : R.drawable.ic_action_hide; + return isGpxFileSelected(app, getGPXFile()) ? R.drawable.ic_action_view : R.drawable.ic_action_hide; } private void initShowButton(final int iconColorDef, final int iconColorPres) { @@ -207,135 +147,4 @@ public class OverviewCard extends BaseCard { } }); } - - private class StatBlockAdapter extends RecyclerView.Adapter { - - private final List statBlocks; - - public StatBlockAdapter(List StatBlocks) { - this.statBlocks = StatBlocks; - } - - @Override - public int getItemCount() { - return statBlocks.size(); - } - - @NonNull - @Override - public StatBlockViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View itemView = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.item_gpx_stat_block, parent, false); - return new StatBlockViewHolder(itemView); - } - - @Override - public void onBindViewHolder(StatBlockViewHolder holder, int position) { - final StatBlock item = statBlocks.get(position); - holder.valueText.setText(item.value); - holder.titleText.setText(item.title); - holder.valueText.setTextColor(getActiveColor()); - holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light)); - holder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (gpxItem != null && gpxItem.analysis != null) { - ArrayList list = new ArrayList<>(); - if (gpxItem.analysis.hasElevationData || gpxItem.analysis.isSpeedSpecified() || gpxItem.analysis.hasSpeedData) { - if (item.firstType != null) { - list.add(item.firstType); - } - if (item.secondType != null) { - list.add(item.secondType); - } - } - gpxItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null; - gpxItem.locationOnMap = gpxItem.locationStart; - - listener.openAnalyzeOnMap(gpxItem); - } - } - }); - setImageDrawable(holder.imageView, item.imageResId, item.imageColorId); - AndroidUtils.setBackgroundColor(view.getContext(), holder.divider, nightMode, R.color.divider_color_light, R.color.divider_color_dark); - AndroidUiHelper.updateVisibility(holder.divider, position != statBlocks.size() - 1); - } - } - - private static class StatBlockViewHolder extends RecyclerView.ViewHolder { - - private final TextViewEx valueText; - private final TextView titleText; - private final AppCompatImageView imageView; - private final View divider; - - StatBlockViewHolder(View view) { - super(view); - valueText = view.findViewById(R.id.value); - titleText = view.findViewById(R.id.title); - imageView = view.findViewById(R.id.image); - divider = view.findViewById(R.id.divider); - } - } - - protected static class StatBlock { - - private final String title; - private final String value; - private final int imageResId; - private final int imageColorId; - private final GPXDataSetType firstType; - private final GPXDataSetType secondType; - private final ItemType itemType; - - public StatBlock(String title, String value, @DrawableRes int imageResId, @ColorRes int imageColorId, - GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) { - this.title = title; - this.value = value; - this.imageResId = imageResId; - this.imageColorId = imageColorId; - this.firstType = firstType; - this.secondType = secondType; - this.itemType = itemType; - } - - public static void prepareData(GPXTrackAnalysis analysis, List listItems, String title, - String value, @DrawableRes int imageResId, @ColorRes int imageColorId, - GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) { - StatBlock statBlock = new StatBlock(title, value, imageResId, imageColorId, firstType, secondType, itemType); - switch (statBlock.itemType) { - case ITEM_DISTANCE: { - if (analysis.totalDistance != 0f) { - listItems.add(statBlock); - } - break; - } - case ITEM_ALTITUDE: { - if (analysis.hasElevationData) { - listItems.add(statBlock); - } - break; - } - case ITEM_SPEED: { - if (analysis.isSpeedSpecified()) { - listItems.add(statBlock); - } - break; - } - case ITEM_TIME: { - if (analysis.hasSpeedData) { - listItems.add(statBlock); - } - break; - } - } - } - - public enum ItemType { - ITEM_DISTANCE, - ITEM_ALTITUDE, - ITEM_SPEED, - ITEM_TIME; - } - } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java index 479c73da5f..6776ea8354 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java @@ -312,7 +312,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } headerContainer.addView(overviewCard.getView()); } else { - overviewCard = new OverviewCard(getMapActivity(), displayHelper, this); + overviewCard = new OverviewCard(getMapActivity(), displayHelper, this, selectedGpxFile); overviewCard.setListener(this); headerContainer.addView(overviewCard.build(getMapActivity())); } @@ -897,6 +897,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card @Override public void updateContent() { + if (overviewCard != null) { + overviewCard.updateContent(); + } if (segmentsCard != null) { segmentsCard.updateContent(); } @@ -1096,7 +1099,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card boolean currentRecording = file == null; String path = file != null ? file.getAbsolutePath() : null; if (context instanceof MapActivity) { - TrackMenuFragment.showInstance((MapActivity) context, path, currentRecording); + TrackMenuFragment.showInstance((MapActivity) context, path, currentRecording, null); } else { Bundle bundle = new Bundle(); bundle.putString(TRACK_FILE_NAME, path); @@ -1106,7 +1109,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } } - public static void showInstance(@NonNull final MapActivity mapActivity, @Nullable String path, boolean showCurrentTrack) { + public static void showInstance(@NonNull final MapActivity mapActivity, @Nullable String path, + boolean showCurrentTrack, @Nullable final LatLon latLon) { OsmandApplication app = mapActivity.getMyApplication(); SelectedGpxFile selectedGpxFile; if (showCurrentTrack) { @@ -1115,7 +1119,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(path); } if (selectedGpxFile != null) { - showInstance(mapActivity, selectedGpxFile, null); + showInstance(mapActivity, selectedGpxFile, latLon); } else if (!Algorithms.isEmpty(path)) { String title = app.getString(R.string.loading_smth, ""); final ProgressDialog progress = ProgressDialog.show(mapActivity, title, app.getString(R.string.loading_data)); @@ -1129,7 +1133,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card OsmandApplication app = mapActivity.getMyApplication(); SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(result, true, false); if (selectedGpxFile != null) { - showInstance(mapActivity, selectedGpxFile, null); + showInstance(mapActivity, selectedGpxFile, latLon); } } if (progress != null && AndroidUtils.isActivityNotDestroyed(mapActivity)) { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/POIMapLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/POIMapLayer.java index 13352a81ee..758588228f 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/POIMapLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/POIMapLayer.java @@ -3,9 +3,11 @@ package net.osmand.plus.views.layers; import android.app.Dialog; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.PointF; import android.graphics.drawable.Drawable; import android.text.util.Linkify; +import android.util.Base64; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; @@ -41,6 +43,7 @@ import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.layers.MapTextLayer.MapTextProvider; +import net.osmand.plus.widgets.WebViewEx; import net.osmand.util.Algorithms; import java.util.ArrayList; @@ -272,7 +275,39 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon } public static void showDescriptionDialog(Context ctx, OsmandApplication app, String text, String title) { - showText(ctx, app, text, title); + final TextView textView = new TextView(ctx); + LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + int textMargin = dpToPx(app, 10f); + boolean light = app.getSettings().isLightContent(); + textView.setLayoutParams(llTextParams); + textView.setPadding(textMargin, textMargin, textMargin, textMargin); + textView.setTextSize(16); + textView.setTextColor(ContextCompat.getColor(app, light ? R.color.text_color_primary_light : R.color.text_color_primary_dark)); + textView.setAutoLinkMask(Linkify.ALL); + textView.setLinksClickable(true); + textView.setText(text); + + showText(ctx, app, textView, title); + } + + public static void showHtmlDescriptionDialog(Context ctx, OsmandApplication app, String html, String title) { + final WebViewEx webView = new WebViewEx(ctx); + LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + webView.setLayoutParams(llTextParams); + int margin = dpToPx(app, 10f); + webView.setPadding(margin, margin, margin, margin); + webView.setScrollbarFadingEnabled(true); + webView.setVerticalScrollBarEnabled(false); + webView.setBackgroundColor(Color.TRANSPARENT); + webView.getSettings().setTextZoom((int) (app.getResources().getConfiguration().fontScale * 100f)); + boolean light = app.getSettings().isLightContent(); + int textColor = ContextCompat.getColor(app, light ? R.color.text_color_primary_light : R.color.text_color_primary_dark); + String rgbHex = Algorithms.colorToString(textColor); + html = "" + html + ""; + String encoded = Base64.encodeToString(html.getBytes(), Base64.NO_PADDING); + webView.loadData(encoded, "text/html", "base64"); + + showText(ctx, app, webView, title); } static int getResIdFromAttribute(final Context ctx, final int attr) { @@ -284,7 +319,7 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon return typedvalueattr.resourceId; } - private static void showText(final Context ctx, final OsmandApplication app, final String text, String title) { + private static void showText(final Context ctx, final OsmandApplication app, final View view, String title) { final Dialog dialog = new Dialog(ctx, app.getSettings().isLightContent() ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme); @@ -306,24 +341,12 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon } }); - final TextView textView = new TextView(ctx); - LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - int textMargin = dpToPx(app, 10f); - boolean light = app.getSettings().isLightContent(); - textView.setLayoutParams(llTextParams); - textView.setPadding(textMargin, textMargin, textMargin, textMargin); - textView.setTextSize(16); - textView.setTextColor(ContextCompat.getColor(app, light ? R.color.text_color_primary_light : R.color.text_color_primary_dark)); - textView.setAutoLinkMask(Linkify.ALL); - textView.setLinksClickable(true); - textView.setText(text); - ScrollView scrollView = new ScrollView(ctx); ll.addView(topBar); LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0); lp.weight = 1; ll.addView(scrollView, lp); - scrollView.addView(textView); + scrollView.addView(view); dialog.setContentView(ll); dialog.setCancelable(true); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/PointLocationLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/PointLocationLayer.java index 21dbbcc7bd..16952876a8 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/PointLocationLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/PointLocationLayer.java @@ -130,7 +130,9 @@ public class PointLocationLayer extends OsmandMapLayer implements ContextMenuLay canvas.restore(); } // Issue 5538: Some devices return positives for hasBearing() at rest, hence add 0.0 check: - boolean isBearing = lastKnownLocation.hasBearing() && (lastKnownLocation.getBearing() != 0.0); + boolean isBearing = lastKnownLocation.hasBearing() && (lastKnownLocation.getBearing() != 0.0) + && (!lastKnownLocation.hasSpeed() || lastKnownLocation.getSpeed() > 0.1); + if (!locationOutdated && isBearing) { float bearing = lastKnownLocation.getBearing(); canvas.rotate(bearing - 90, locationX, locationY); diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/menu/WikivoyageWptPtMenuBuilder.java b/OsmAnd/src/net/osmand/plus/wikivoyage/menu/WikivoyageWptPtMenuBuilder.java index 9bc991422d..bca5943212 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/menu/WikivoyageWptPtMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/menu/WikivoyageWptPtMenuBuilder.java @@ -2,8 +2,6 @@ package net.osmand.plus.wikivoyage.menu; import android.view.View; -import androidx.annotation.NonNull; - import net.osmand.GPXUtilities.WptPt; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; @@ -12,6 +10,8 @@ import net.osmand.util.Algorithms; import java.util.HashMap; +import androidx.annotation.NonNull; + public class WikivoyageWptPtMenuBuilder extends WptPtMenuBuilder { private final static String KEY_PHONE = "Phone: "; @@ -30,12 +30,13 @@ public class WikivoyageWptPtMenuBuilder extends WptPtMenuBuilder { @Override protected void buildDescription(View view) { - final String desc = descTokens.get(KEY_DESCRIPTION); + String desc = descTokens.get(KEY_DESCRIPTION); if (!Algorithms.isEmpty(desc)) { - buildDescriptionRow(view, app.getString(R.string.shared_string_description), desc, 0, 10, true); + buildDescriptionRow(view, desc); } } + @Override protected void prepareDescription(final WptPt wpt, View view) { String phones = descTokens.get(KEY_PHONE);