diff --git a/.github/ISSUE_TEMPLATE/3-bug-report.md b/.github/ISSUE_TEMPLATE/2-bug-report.md similarity index 100% rename from .github/ISSUE_TEMPLATE/3-bug-report.md rename to .github/ISSUE_TEMPLATE/2-bug-report.md diff --git a/.github/ISSUE_TEMPLATE/2-faq-report.md b/.github/ISSUE_TEMPLATE/2-faq-report.md deleted file mode 100644 index 531d263d7f..0000000000 --- a/.github/ISSUE_TEMPLATE/2-faq-report.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: "📚 Outdated FAQ" -about: Report an issue in FAQ ---- - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 - -Please do not file FAQ issues on the GitHub issues tracker. - -Instead use the [Google group](https://groups.google.com/forum/#!forum/osmand) to fix wrong or outdated FAQ. - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/4-routing-report.md b/.github/ISSUE_TEMPLATE/3-routing-report.md similarity index 100% rename from .github/ISSUE_TEMPLATE/4-routing-report.md rename to .github/ISSUE_TEMPLATE/3-routing-report.md diff --git a/.github/ISSUE_TEMPLATE/5-feature-request.md b/.github/ISSUE_TEMPLATE/4-feature-request.md similarity index 100% rename from .github/ISSUE_TEMPLATE/5-feature-request.md rename to .github/ISSUE_TEMPLATE/4-feature-request.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..bca7b3f727 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +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 diff --git a/OsmAnd-api/src/net/osmand/aidlapi/customization/ProfileSettingsParams.java b/OsmAnd-api/src/net/osmand/aidlapi/customization/ProfileSettingsParams.java index a22d4e3c91..8d4be54a23 100644 --- a/OsmAnd-api/src/net/osmand/aidlapi/customization/ProfileSettingsParams.java +++ b/OsmAnd-api/src/net/osmand/aidlapi/customization/ProfileSettingsParams.java @@ -38,6 +38,11 @@ public class ProfileSettingsParams extends AidlParams { this.silent = silent; } + public ProfileSettingsParams(Uri profileSettingsUri, List settingsTypeList, + boolean replace, String latestChanges, int version) { + this(profileSettingsUri, settingsTypeList, replace, false, latestChanges, version); + } + public ProfileSettingsParams(Parcel in) { readFromParcel(in); } diff --git a/OsmAnd-java/src/main/java/net/osmand/PlatformUtil.java b/OsmAnd-java/src/main/java/net/osmand/PlatformUtil.java index ffc9bf05b0..fd3fa2e2eb 100644 --- a/OsmAnd-java/src/main/java/net/osmand/PlatformUtil.java +++ b/OsmAnd-java/src/main/java/net/osmand/PlatformUtil.java @@ -23,7 +23,9 @@ public class PlatformUtil { } public static XmlPullParser newXMLPullParser() throws XmlPullParserException{ - return new org.kxml2.io.KXmlParser(); + org.kxml2.io.KXmlParser xmlParser = new org.kxml2.io.KXmlParser(); + xmlParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + return xmlParser; } public static XmlSerializer newSerializer() { 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/layout/fragment_opr_login.xml b/OsmAnd/res/layout/fragment_opr_login.xml index e941075f54..ee969b1a74 100644 --- a/OsmAnd/res/layout/fragment_opr_login.xml +++ b/OsmAnd/res/layout/fragment_opr_login.xml @@ -1,36 +1,22 @@ - + - + android:gravity="center_vertical" + android:padding="0dp" /> - - - - - + android:layout_height="0dp" + android:layout_weight="1"> + app:typeface="@string/font_roboto_regular" /> + - + + - \ No newline at end of file + \ No newline at end of file diff --git a/OsmAnd/res/layout/subscription_fragment.xml b/OsmAnd/res/layout/subscription_fragment.xml index 59b6f9b1b8..ad308e6be1 100644 --- a/OsmAnd/res/layout/subscription_fragment.xml +++ b/OsmAnd/res/layout/subscription_fragment.xml @@ -1,5 +1,4 @@ - @@ -19,19 +19,19 @@ android:layout_width="52dp" android:layout_height="52dp" android:contentDescription="@string/shared_string_close" - app:srcCompat="@drawable/ic_action_remove_dark"/> + app:srcCompat="@drawable/ic_action_remove_dark" /> + app:typeface="@string/font_roboto_regular" /> @@ -39,7 +39,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + @@ -76,54 +76,81 @@ android:layout_width="56dp" android:layout_height="48dp" android:scaleType="center" - app:srcCompat="@drawable/ic_action_osm_live" - android:tint="@color/osmand_orange"/> + android:tint="@color/osmand_orange" + app:srcCompat="@drawable/ic_action_osm_live" /> + android:textColor="?android:attr/textColorPrimary" /> + android:orientation="horizontal"> + android:layout_marginTop="@dimen/context_menu_second_line_top_margin" + android:layout_marginStart="@dimen/list_content_padding" + android:layout_marginLeft="@dimen/list_content_padding" + android:paddingStart="@dimen/local_size_height" + android:paddingLeft="@dimen/local_size_height" + android:paddingEnd="@dimen/local_size_height" + android:paddingRight="@dimen/local_size_height" + android:text="@string/donation_to_osm" /> - + android:minHeight="56dp" + android:orientation="vertical"> + + + + + + @@ -140,13 +167,13 @@ android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginBottom="6dp" - android:background="?attr/dashboard_divider"/> + android:background="?attr/dashboard_divider" /> @@ -155,47 +182,48 @@ android:layout_width="56dp" android:layout_height="48dp" android:scaleType="center" - app:srcCompat="@drawable/ic_world_globe_dark"/> + app:srcCompat="@drawable/ic_world_globe_dark" /> + android:layout_marginEnd="16dp" + android:layout_marginRight="16dp" + android:orientation="vertical"> + android:textColor="?android:attr/textColorSecondary" /> + app:drawableEndCompat="@drawable/ic_action_arrow_drop_down" + app:drawableRightCompat="@drawable/ic_action_arrow_drop_down" /> + android:textColor="?android:attr/textColorSecondary" /> @@ -213,21 +241,21 @@ android:layout_width="56dp" android:layout_height="48dp" android:scaleType="center" - app:srcCompat="@drawable/ic_action_message"/> + app:srcCompat="@drawable/ic_action_message" /> + android:paddingStart="2dp" + android:paddingLeft="2dp" /> @@ -235,14 +263,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" + android:layout_marginStart="72dp" android:layout_marginLeft="72dp" + android:layout_marginEnd="16dp" android:layout_marginRight="16dp" + android:paddingStart="2dp" android:paddingLeft="2dp" android:text="@string/osm_live_email_desc" - android:textColor="?android:attr/textColorSecondary" - android:paddingStart="2dp" - android:layout_marginStart="72dp" - android:layout_marginEnd="16dp" /> + android:textColor="?android:attr/textColorSecondary" /> + app:srcCompat="@drawable/ic_action_user" /> + android:paddingStart="2dp" + android:paddingLeft="2dp" /> @@ -284,16 +312,16 @@ android:id="@+id/hideUserNameCheckbox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="12dp" + android:layout_marginStart="72dp" android:layout_marginLeft="72dp" - android:layout_marginRight="16dp" android:layout_marginTop="8dp" + android:layout_marginEnd="16dp" + android:layout_marginRight="16dp" + android:layout_marginBottom="12dp" + android:paddingStart="4dp" android:paddingLeft="4dp" android:text="@string/osm_live_hide_user_name" - android:textColor="?android:attr/textColorPrimary" - android:layout_marginEnd="16dp" - android:paddingStart="4dp" - android:layout_marginStart="72dp" /> + android:textColor="?android:attr/textColorPrimary" /> @@ -303,35 +331,35 @@ android:id="@+id/editModeBottomView" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="16dp" android:layout_marginTop="16dp" + android:layout_marginBottom="16dp" android:visibility="visible">