Merge branch 'master' of ssh://github.com/osmandapp/Osmand into TelegramImprovements
This commit is contained in:
commit
bdeed810fc
26 changed files with 461 additions and 145 deletions
|
@ -309,9 +309,10 @@ public class SearchUICore {
|
|||
|
||||
public void init() {
|
||||
apis.add(new SearchCoreFactory.SearchLocationAndUrlAPI());
|
||||
apis.add(new SearchCoreFactory.SearchAmenityTypesAPI(poiTypes));
|
||||
apis.add(new SearchCoreFactory.SearchAmenityByTypeAPI(poiTypes));
|
||||
apis.add(new SearchCoreFactory.SearchAmenityByNameAPI());
|
||||
SearchAmenityTypesAPI searchAmenityTypesAPI = new SearchAmenityTypesAPI(poiTypes);
|
||||
apis.add(searchAmenityTypesAPI);
|
||||
apis.add(new SearchCoreFactory.SearchAmenityByTypeAPI(poiTypes, searchAmenityTypesAPI));
|
||||
apis.add(new SearchCoreFactory.SearchAmenityByNameAPI(searchAmenityTypesAPI));
|
||||
SearchBuildingAndIntersectionsByStreetAPI streetsApi =
|
||||
new SearchCoreFactory.SearchBuildingAndIntersectionsByStreetAPI();
|
||||
apis.add(streetsApi);
|
||||
|
|
|
@ -500,14 +500,20 @@ public class SearchCoreFactory {
|
|||
private static final int LIMIT = 10000;
|
||||
private static final int BBOX_RADIUS = 500 * 1000;
|
||||
private static final int BBOX_RADIUS_INSIDE = 10000 * 1000; // to support city search for basemap
|
||||
private SearchAmenityTypesAPI searchAmenityTypesAPI;
|
||||
|
||||
public SearchAmenityByNameAPI() {
|
||||
public SearchAmenityByNameAPI(SearchAmenityTypesAPI searchAmenityTypesAPI) {
|
||||
super(ObjectType.POI);
|
||||
this.searchAmenityTypesAPI = searchAmenityTypesAPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException {
|
||||
if(!phrase.isUnknownSearchWordPresent()) {
|
||||
if (!phrase.isUnknownSearchWordPresent()) {
|
||||
return false;
|
||||
}
|
||||
if (phrase.isNoSelectedType() && phrase.isUnknownSearchWordPresent()
|
||||
&& phrase.isUnknownSearchWordComplete() && searchAmenityTypesAPI.hasFoundPoiTypes()) {
|
||||
return false;
|
||||
}
|
||||
final BinaryMapIndexReader[] currentFile = new BinaryMapIndexReader[1];
|
||||
|
@ -602,7 +608,7 @@ public class SearchCoreFactory {
|
|||
public int getMinimalSearchRadius(SearchPhrase phrase) {
|
||||
return phrase.getRadiusSearch(BBOX_RADIUS);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getNextSearchRadius(SearchPhrase phrase) {
|
||||
return phrase.getNextRadiusSearch(BBOX_RADIUS);
|
||||
|
@ -619,12 +625,30 @@ public class SearchCoreFactory {
|
|||
private List<CustomSearchPoiFilter> customPoiFilters = new ArrayList<>();
|
||||
private TIntArrayList customPoiFiltersPriorites = new TIntArrayList();
|
||||
private MapPoiTypes types;
|
||||
private List<AbstractPoiType> foundPoiTypes = new ArrayList<>();
|
||||
private SearchPhrase lastSearchedPhrase;
|
||||
|
||||
public SearchAmenityTypesAPI(MapPoiTypes types) {
|
||||
super(ObjectType.POI_TYPE);
|
||||
this.types = types;
|
||||
}
|
||||
|
||||
public List<AbstractPoiType> getFoundPoiTypes() {
|
||||
return foundPoiTypes;
|
||||
}
|
||||
|
||||
public boolean hasFoundPoiTypes() {
|
||||
return foundPoiTypes.size() > 0;
|
||||
}
|
||||
|
||||
public SearchPhrase getLastSearchedPhrase() {
|
||||
return lastSearchedPhrase;
|
||||
}
|
||||
|
||||
public void setLastSearchedPhrase(SearchPhrase lastSearchedPhrase) {
|
||||
this.lastSearchedPhrase = lastSearchedPhrase;
|
||||
}
|
||||
|
||||
public void clearCustomFilters() {
|
||||
this.customPoiFilters.clear();
|
||||
this.customPoiFiltersPriorites.clear();
|
||||
|
@ -642,7 +666,6 @@ public class SearchCoreFactory {
|
|||
topVisibleFilters = types.getTopVisibleFilters();
|
||||
categories = types.getCategories(false);
|
||||
}
|
||||
// results.clear();
|
||||
List<AbstractPoiType> results = new ArrayList<AbstractPoiType>();
|
||||
NameStringMatcher nm = phrase.getNameStringMatcher();
|
||||
for (PoiFilter pf : topVisibleFilters) {
|
||||
|
@ -687,28 +710,32 @@ public class SearchCoreFactory {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (AbstractPoiType pt : results) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = pt.getTranslation();
|
||||
res.object = pt;
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY;
|
||||
res.priorityDistance = 0;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
for (int i = 0; i < customPoiFilters.size(); i++) {
|
||||
CustomSearchPoiFilter csf = customPoiFilters.get(i);
|
||||
int p = customPoiFiltersPriorites.get(i);
|
||||
if (!phrase.isUnknownSearchWordPresent() || nm.matches(csf.getName())) {
|
||||
foundPoiTypes = new ArrayList<>(results);
|
||||
lastSearchedPhrase = phrase;
|
||||
|
||||
if (resultMatcher != null) {
|
||||
for (AbstractPoiType pt : results) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = csf.getName();
|
||||
res.object = csf;
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + p;
|
||||
res.localeName = pt.getTranslation();
|
||||
res.object = pt;
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY;
|
||||
res.priorityDistance = 0;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
for (int i = 0; i < customPoiFilters.size(); i++) {
|
||||
CustomSearchPoiFilter csf = customPoiFilters.get(i);
|
||||
int p = customPoiFiltersPriorites.get(i);
|
||||
if (!phrase.isUnknownSearchWordPresent() || nm.matches(csf.getName())) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = csf.getName();
|
||||
res.object = csf;
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + p;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -733,12 +760,14 @@ public class SearchCoreFactory {
|
|||
|
||||
public static class SearchAmenityByTypeAPI extends SearchBaseAPI {
|
||||
private static final int BBOX_RADIUS = 10000;
|
||||
private SearchAmenityTypesAPI searchAmenityTypesAPI;
|
||||
|
||||
private MapPoiTypes types;
|
||||
|
||||
public SearchAmenityByTypeAPI(MapPoiTypes types) {
|
||||
public SearchAmenityByTypeAPI(MapPoiTypes types, SearchAmenityTypesAPI searchAmenityTypesAPI) {
|
||||
super(ObjectType.POI);
|
||||
this.types = types;
|
||||
this.searchAmenityTypesAPI = searchAmenityTypesAPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -750,7 +779,7 @@ public class SearchCoreFactory {
|
|||
public int getMinimalSearchRadius(SearchPhrase phrase) {
|
||||
return phrase.getRadiusSearch(BBOX_RADIUS);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getNextSearchRadius(SearchPhrase phrase) {
|
||||
return phrase.getNextRadiusSearch(BBOX_RADIUS);
|
||||
|
@ -792,29 +821,54 @@ public class SearchCoreFactory {
|
|||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS);
|
||||
List<BinaryMapIndexReader> oo = phrase.getOfflineIndexes();
|
||||
Set<String> searchedPois = new TreeSet<>();
|
||||
for (BinaryMapIndexReader o : oo) {
|
||||
ResultMatcher<Amenity> rm = getResultMatcher(phrase, resultMatcher, o, searchedPois);
|
||||
if (obj instanceof CustomSearchPoiFilter) {
|
||||
rm = ((CustomSearchPoiFilter) obj).wrapResultMatcher(rm);
|
||||
searchPoi(phrase, resultMatcher, obj, null, ptf);
|
||||
} else if (searchAmenityTypesAPI != null) {
|
||||
if (searchAmenityTypesAPI.lastSearchedPhrase == null
|
||||
|| !searchAmenityTypesAPI.lastSearchedPhrase.getUnknownSearchPhrase().equals(phrase.getUnknownSearchPhrase())) {
|
||||
searchAmenityTypesAPI.search(phrase, null);
|
||||
}
|
||||
List<AbstractPoiType> poiTypes = searchAmenityTypesAPI.getFoundPoiTypes();
|
||||
for (AbstractPoiType pt : poiTypes) {
|
||||
SearchPoiTypeFilter ptf = getPoiTypeFilter(pt);
|
||||
String customName = phrase.getPoiNameFilter(pt);
|
||||
if (customName != null) {
|
||||
phrase.setUnknownSearchWordPoiType(pt);
|
||||
searchPoi(phrase, resultMatcher, null, customName, ptf);
|
||||
break;
|
||||
}
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
(int)bbox.left, (int)bbox.right,
|
||||
(int)bbox.top, (int)bbox.bottom, -1, ptf,
|
||||
rm);
|
||||
o.searchPoi(req);
|
||||
resultMatcher.apiSearchRegionFinished(this, o, phrase);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void searchPoi(SearchPhrase phrase, SearchResultMatcher resultMatcher, Object obj, String customName, SearchPoiTypeFilter ptf) throws IOException {
|
||||
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS);
|
||||
List<BinaryMapIndexReader> oo = phrase.getOfflineIndexes();
|
||||
Set<String> searchedPois = new TreeSet<>();
|
||||
for (BinaryMapIndexReader o : oo) {
|
||||
ResultMatcher<Amenity> rm = getResultMatcher(phrase, resultMatcher, customName, o, searchedPois);
|
||||
if (obj instanceof CustomSearchPoiFilter) {
|
||||
rm = ((CustomSearchPoiFilter) obj).wrapResultMatcher(rm);
|
||||
}
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
(int) bbox.left, (int) bbox.right,
|
||||
(int) bbox.top, (int) bbox.bottom, -1, ptf,
|
||||
rm);
|
||||
o.searchPoi(req);
|
||||
resultMatcher.apiSearchRegionFinished(this, o, phrase);
|
||||
}
|
||||
}
|
||||
|
||||
private ResultMatcher<Amenity> getResultMatcher(final SearchPhrase phrase, final SearchResultMatcher resultMatcher,
|
||||
final BinaryMapIndexReader selected, final Set<String> searchedPois) {
|
||||
final NameStringMatcher ns = phrase.getNameStringMatcher();
|
||||
final String customName, final BinaryMapIndexReader selected,
|
||||
final Set<String> searchedPois) {
|
||||
final NameStringMatcher ns;
|
||||
final boolean hasCustomName = !Algorithms.isEmpty(customName);
|
||||
if (hasCustomName) {
|
||||
ns = phrase.getNameStringMatcher(customName, phrase.isLastUnknownSearchWordComplete());
|
||||
} else {
|
||||
ns = phrase.getNameStringMatcher();
|
||||
}
|
||||
return new ResultMatcher<Amenity>() {
|
||||
|
||||
@Override
|
||||
|
@ -846,7 +900,7 @@ public class SearchCoreFactory {
|
|||
res.preferredZoom = 17;
|
||||
res.file = selected;
|
||||
res.location = object.getLocation();
|
||||
res.priority = SEARCH_AMENITY_BY_TYPE_PRIORITY;
|
||||
res.priority = hasCustomName ? SEARCH_AMENITY_TYPE_PRIORITY - 1 : SEARCH_AMENITY_BY_TYPE_PRIORITY;
|
||||
res.priorityDistance = 1;
|
||||
res.objectType = ObjectType.POI;
|
||||
resultMatcher.publish(res);
|
||||
|
@ -894,13 +948,12 @@ public class SearchCoreFactory {
|
|||
|
||||
@Override
|
||||
public int getSearchPriority(SearchPhrase p) {
|
||||
if (p.isLastWord(ObjectType.POI_TYPE) &&
|
||||
p.getLastTokenLocation() != null) {
|
||||
if ((p.isLastWord(ObjectType.POI_TYPE) && p.getLastTokenLocation() != null)
|
||||
|| (p.isNoSelectedType() && p.isUnknownSearchWordComplete())) {
|
||||
return SEARCH_AMENITY_BY_TYPE_PRIORITY;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,10 +5,11 @@ import net.osmand.CollatorStringMatcher;
|
|||
import net.osmand.CollatorStringMatcher.StringMatcherMode;
|
||||
import net.osmand.StringMatcher;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.binary.CommonWords;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
import net.osmand.binary.CommonWords;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.osm.AbstractPoiType;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
|
@ -33,7 +34,8 @@ public class SearchPhrase {
|
|||
private List<NameStringMatcher> unknownWordsMatcher = new ArrayList<>();
|
||||
private String unknownSearchWordTrim;
|
||||
private String unknownSearchPhrase = "";
|
||||
|
||||
private AbstractPoiType unknownSearchWordPoiType;
|
||||
|
||||
private NameStringMatcher sm;
|
||||
private SearchSettings settings;
|
||||
private List<BinaryMapIndexReader> indexes;
|
||||
|
@ -223,8 +225,42 @@ public class SearchPhrase {
|
|||
public int getUnknownSearchWordLength() {
|
||||
return unknownSearchWordTrim.length() ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public AbstractPoiType getUnknownSearchWordPoiType() {
|
||||
return unknownSearchWordPoiType;
|
||||
}
|
||||
|
||||
public void setUnknownSearchWordPoiType(AbstractPoiType unknownSearchWordPoiType) {
|
||||
this.unknownSearchWordPoiType = unknownSearchWordPoiType;
|
||||
}
|
||||
|
||||
public boolean hasUnknownSearchWordPoiType() {
|
||||
return unknownSearchWordPoiType != null;
|
||||
}
|
||||
|
||||
public String getPoiNameFilter() {
|
||||
return getPoiNameFilter(unknownSearchWordPoiType);
|
||||
}
|
||||
|
||||
public String getPoiNameFilter(AbstractPoiType pt) {
|
||||
String nameFilter = null;
|
||||
if (pt != null) {
|
||||
NameStringMatcher nm = getNameStringMatcher(getUnknownSearchWord(), true);
|
||||
String unknownSearchPhrase = getUnknownSearchPhrase();
|
||||
String enTranslation = pt.getEnTranslation();
|
||||
String translation = pt.getTranslation();
|
||||
String synonyms = pt.getSynonyms();
|
||||
if (unknownSearchPhrase.length() > enTranslation.length() && nm.matches(enTranslation)) {
|
||||
nameFilter = unknownSearchPhrase.substring(enTranslation.length()).trim();
|
||||
} else if (unknownSearchPhrase.length() > translation.length() && nm.matches(translation)) {
|
||||
nameFilter = unknownSearchPhrase.substring(translation.length()).trim();
|
||||
} else if (unknownSearchPhrase.length() > synonyms.length() && nm.matches(synonyms)) {
|
||||
nameFilter = unknownSearchPhrase.substring(synonyms.length()).trim();
|
||||
}
|
||||
}
|
||||
return nameFilter;
|
||||
}
|
||||
|
||||
public QuadRect getRadiusBBoxToSearch(int radius) {
|
||||
int radiusInMeters = getRadiusSearch(radius);
|
||||
QuadRect cache1kmRect = get1km31Rect();
|
||||
|
|
|
@ -24,10 +24,15 @@ public class LocationParser {
|
|||
return new LatLon(codeArea.getCenterLatitude(), codeArea.getCenterLongitude());
|
||||
}
|
||||
}
|
||||
if (locPhrase.length() == 0 || !(locPhrase.charAt(0) == '-' || Character.isDigit(locPhrase.charAt(0))
|
||||
|| locPhrase.charAt(0) == 'S' || locPhrase.charAt(0) == 's'
|
||||
|| locPhrase.charAt(0) == 'N' || locPhrase.charAt(0) == 'n'
|
||||
|| locPhrase.contains("://"))) {
|
||||
boolean valid = isValidLocPhrase(locPhrase);
|
||||
if (!valid) {
|
||||
String[] split = locPhrase.split(" ");
|
||||
if (split.length == 4 && split[1].contains(".") && split[3].contains(".")) {
|
||||
locPhrase = split[1] + " " + split[3];
|
||||
valid = isValidLocPhrase(locPhrase);
|
||||
}
|
||||
}
|
||||
if (!valid) {
|
||||
return null;
|
||||
}
|
||||
List<Double> d = new ArrayList<>();
|
||||
|
@ -43,7 +48,7 @@ public class LocationParser {
|
|||
if (Character.isLetter(ch)) {
|
||||
UTMPoint upoint = new UTMPoint(d.get(2), d.get(1), d.get(0).intValue(), ch);
|
||||
LatLonPoint ll = upoint.toLatLonPoint();
|
||||
return new LatLon(ll.getLatitude(), ll.getLongitude());
|
||||
return validateAndCreateLatLon(ll.getLatitude(), ll.getLongitude());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +62,7 @@ public class LocationParser {
|
|||
UTMPoint upoint = new UTMPoint(Double.parseDouble(north), Double.parseDouble(east), d.get(0)
|
||||
.intValue(), ch);
|
||||
LatLonPoint ll = upoint.toLatLonPoint();
|
||||
return new LatLon(ll.getLatitude(), ll.getLongitude());
|
||||
return validateAndCreateLatLon(ll.getLatitude(), ll.getLongitude());
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
|
@ -125,10 +130,10 @@ public class LocationParser {
|
|||
if (split != -1) {
|
||||
double lat = parse1Coordinate(all, 0, split);
|
||||
double lon = parse1Coordinate(all, split, all.size());
|
||||
return new LatLon(lat, lon);
|
||||
return validateAndCreateLatLon(lat, lon);
|
||||
}
|
||||
if (d.size() == 2) {
|
||||
return new LatLon(d.get(0), d.get(1));
|
||||
return validateAndCreateLatLon(d.get(0), d.get(1));
|
||||
}
|
||||
// simple url case
|
||||
if (locPhrase.contains("://")) {
|
||||
|
@ -147,7 +152,7 @@ public class LocationParser {
|
|||
}
|
||||
}
|
||||
if (lat != 0 && lon != 0 && only2decimals) {
|
||||
return new LatLon(lat, lon);
|
||||
return validateAndCreateLatLon(lat, lon);
|
||||
}
|
||||
}
|
||||
// split by equal number of digits
|
||||
|
@ -166,12 +171,27 @@ public class LocationParser {
|
|||
if (splitEq != -1) {
|
||||
double lat = parse1Coordinate(all, 0, splitEq);
|
||||
double lon = parse1Coordinate(all, splitEq, all.size());
|
||||
return new LatLon(lat, lon);
|
||||
return validateAndCreateLatLon(lat, lon);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static LatLon validateAndCreateLatLon(double lat, double lon) {
|
||||
if (Math.abs(lat) <= 90 && Math.abs(lon) <= 180) {
|
||||
return new LatLon(lat, lon);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isValidLocPhrase(String locPhrase) {
|
||||
if (!locPhrase.isEmpty()) {
|
||||
char ch = Character.toLowerCase(locPhrase.charAt(0));
|
||||
return ch == '-' || Character.isDigit(ch) || ch == 's' || ch == 'n' || locPhrase.contains("://");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static double parse1Coordinate(List<Object> all, int begin, int end) {
|
||||
boolean neg = false;
|
||||
double d = 0;
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_regular"
|
||||
tools:text="@string/expire_in" />
|
||||
tools:text="@string/expire_at" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/ending_in_first_part"
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<string name="send_my_location">Send my location</string>
|
||||
<string name="gps_and_location">GPS & location</string>
|
||||
<string name="sharing_time">Sharing time</string>
|
||||
<string name="expire_in">Expire in</string>
|
||||
<string name="expire_at">Expire at</string>
|
||||
<string name="stop_sharing_all">Sharing is enabled (disable)</string>
|
||||
<string name="turn_off_location_sharing">Turn off location sharing</string>
|
||||
<string name="open_osmand">Open OsmAnd</string>
|
||||
|
|
|
@ -26,6 +26,7 @@ private val LOC_HISTORY_VALUES_SEC = listOf(
|
|||
12 * 60 * 60L,
|
||||
24 * 60 * 60L
|
||||
)
|
||||
private val MESSAGE_ADD_ACTIVE_TIME_VALUES_SEC = listOf(15 * 60L, 30 * 60L, 60 * 60L, 180 * 60L)
|
||||
|
||||
private const val SEND_MY_LOC_DEFAULT_INDEX = 6
|
||||
private const val STALE_LOC_DEFAULT_INDEX = 4
|
||||
|
@ -57,6 +58,8 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
private var chatLivePeriods = mutableMapOf<Long, Long>()
|
||||
private var chatShareLocStartSec = mutableMapOf<Long, Long>()
|
||||
|
||||
private var chatShareAddActiveTime = mutableMapOf<Long, Long>()
|
||||
|
||||
private var shareLocationChats: Set<Long> = emptySet()
|
||||
private var hiddenOnMapChats: Set<Long> = emptySet()
|
||||
|
@ -104,6 +107,10 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
presentChatIds.contains(key)
|
||||
}.toMutableMap()
|
||||
|
||||
chatShareAddActiveTime = chatShareAddActiveTime.filter { (key, _) ->
|
||||
presentChatIds.contains(key)
|
||||
}.toMutableMap()
|
||||
|
||||
chatShareLocStartSec = chatShareLocStartSec.filter { (key, _) ->
|
||||
presentChatIds.contains(key)
|
||||
}.toMutableMap()
|
||||
|
@ -112,7 +119,8 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
fun shareLocationToChat(
|
||||
chatId: Long,
|
||||
share: Boolean,
|
||||
livePeriod: Long = DEFAULT_VISIBLE_TIME_SECONDS
|
||||
livePeriod: Long = DEFAULT_VISIBLE_TIME_SECONDS,
|
||||
addActiveTime: Long = MESSAGE_ADD_ACTIVE_TIME_VALUES_SEC[0]
|
||||
) {
|
||||
val shareLocationChats = shareLocationChats.toMutableList()
|
||||
if (share) {
|
||||
|
@ -123,11 +131,13 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
}
|
||||
chatLivePeriods[chatId] = lp
|
||||
chatShareLocStartSec[chatId] = (System.currentTimeMillis() / 1000)
|
||||
chatShareAddActiveTime[chatId] = addActiveTime
|
||||
shareLocationChats.add(chatId)
|
||||
} else {
|
||||
shareLocationChats.remove(chatId)
|
||||
chatLivePeriods.remove(chatId)
|
||||
chatShareLocStartSec.remove(chatId)
|
||||
chatShareAddActiveTime.remove(chatId)
|
||||
}
|
||||
this.shareLocationChats = shareLocationChats.toHashSet()
|
||||
}
|
||||
|
@ -141,6 +151,21 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
fun getChatLivePeriod(chatId: Long) = chatLivePeriods[chatId]
|
||||
|
||||
fun getChatAddActiveTime(chatId: Long) = chatShareAddActiveTime[chatId] ?: MESSAGE_ADD_ACTIVE_TIME_VALUES_SEC[0]
|
||||
|
||||
fun getChatNextAddActiveTime(chatId: Long): Long {
|
||||
return if (chatShareAddActiveTime.containsKey(chatId)) {
|
||||
var index = MESSAGE_ADD_ACTIVE_TIME_VALUES_SEC.indexOf(chatShareAddActiveTime[chatId])
|
||||
if (MESSAGE_ADD_ACTIVE_TIME_VALUES_SEC.lastIndex > index) {
|
||||
MESSAGE_ADD_ACTIVE_TIME_VALUES_SEC[++index]
|
||||
} else {
|
||||
MESSAGE_ADD_ACTIVE_TIME_VALUES_SEC[index]
|
||||
}
|
||||
} else {
|
||||
MESSAGE_ADD_ACTIVE_TIME_VALUES_SEC[0]
|
||||
}
|
||||
}
|
||||
|
||||
fun getChatLivePeriods(): Map<Long, Long> {
|
||||
return chatLivePeriods.filter {
|
||||
getChatLiveMessageExpireTime(it.key) > 0
|
||||
|
@ -163,10 +188,15 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
chatShareLocStartSec[chatId] = startTime
|
||||
}
|
||||
|
||||
fun updateChatAddActiveTime(chatId: Long, newTime: Long) {
|
||||
chatShareAddActiveTime[chatId] = newTime
|
||||
}
|
||||
|
||||
fun stopSharingLocationToChats() {
|
||||
this.shareLocationChats = emptySet()
|
||||
this.chatLivePeriods.clear()
|
||||
this.chatShareLocStartSec.clear()
|
||||
this.chatShareAddActiveTime.clear()
|
||||
}
|
||||
|
||||
fun showChatOnMap(chatId: Long, show: Boolean) {
|
||||
|
|
|
@ -31,6 +31,7 @@ class TelegramHelper private constructor() {
|
|||
private const val DEVICE_PREFIX = "Device: "
|
||||
private const val LOCATION_PREFIX = "Location: "
|
||||
private const val LAST_LOCATION_PREFIX = "Last location: "
|
||||
private const val UPDATED_PREFIX = "Updated: "
|
||||
|
||||
private const val FEW_SECONDS_AGO = "few seconds ago"
|
||||
private const val SECONDS_AGO_SUFFIX = " seconds ago"
|
||||
|
@ -796,7 +797,11 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
|
||||
private fun TdApi.Message.isAppropriate(): Boolean {
|
||||
if (isOutgoing || isChannelPost) {
|
||||
if (isChannelPost) {
|
||||
return false
|
||||
}
|
||||
val isOsmAndBot = isOsmAndBot(senderUserId) || isOsmAndBot(viaBotUserId)
|
||||
if (isOutgoing && !isOsmAndBot) {
|
||||
return false
|
||||
}
|
||||
val lastEdited = Math.max(date, editDate)
|
||||
|
@ -806,8 +811,7 @@ class TelegramHelper private constructor() {
|
|||
val content = content
|
||||
return when (content) {
|
||||
is TdApi.MessageLocation -> true
|
||||
is TdApi.MessageText -> (isOsmAndBot(senderUserId) || isOsmAndBot(viaBotUserId))
|
||||
&& content.text.text.startsWith(DEVICE_PREFIX)
|
||||
is TdApi.MessageText -> (isOsmAndBot) && content.text.text.startsWith(DEVICE_PREFIX)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
@ -870,6 +874,13 @@ class TelegramHelper private constructor() {
|
|||
}
|
||||
}
|
||||
}
|
||||
s.startsWith(UPDATED_PREFIX) -> {
|
||||
if (res.lastUpdated == 0) {
|
||||
val updatedStr = s.removePrefix(UPDATED_PREFIX)
|
||||
val updatedS = updatedStr.substring(0, updatedStr.indexOf("("))
|
||||
res.lastUpdated = (parseTime(updatedS.trim()) / 1000).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
|
|
|
@ -30,8 +30,6 @@ private const val DEFAULT_CHAT = 0
|
|||
|
||||
private const val ADAPTER_UPDATE_INTERVAL_MIL = 5 * 1000L // 5 sec
|
||||
|
||||
private const val MESSAGE_ADD_ACTIVE_TIME_SEC = 30 * 60L // 30 min
|
||||
|
||||
class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||
|
||||
private var textMarginSmall: Int = 0
|
||||
|
@ -578,13 +576,14 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
|
||||
holder.textInArea?.apply {
|
||||
visibility = View.VISIBLE
|
||||
text = "${getText(R.string.plus)} ${OsmandFormatter.getFormattedDuration(context!!,
|
||||
MESSAGE_ADD_ACTIVE_TIME_SEC)}"
|
||||
text = "${getText(R.string.plus)} ${OsmandFormatter.getFormattedDuration(
|
||||
context!!, settings.getChatAddActiveTime(chat.id))}"
|
||||
setOnClickListener {
|
||||
val newLivePeriod = settings.getChatLiveMessageExpireTime(chat.id) + MESSAGE_ADD_ACTIVE_TIME_SEC
|
||||
val chatNextAddTime = settings.getChatNextAddActiveTime(chat.id)
|
||||
val newLivePeriod = settings.getChatLiveMessageExpireTime(chat.id) + settings.getChatAddActiveTime(chat.id)
|
||||
settings.shareLocationToChat(chat.id, false)
|
||||
telegramHelper.stopSendingLiveLocationToChat(chat.id)
|
||||
settings.shareLocationToChat(chat.id, true, newLivePeriod)
|
||||
settings.shareLocationToChat(chat.id, true, newLivePeriod, chatNextAddTime)
|
||||
app.forceUpdateMyLocation()
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
|
@ -592,7 +591,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
|||
|
||||
holder.stopSharingDescr?.apply {
|
||||
visibility = getStopSharingVisibility(expiresIn)
|
||||
text = "${getText(R.string.expire_in)}:"
|
||||
text = getText(R.string.expire_at)
|
||||
}
|
||||
|
||||
holder.stopSharingFirstPart?.apply {
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:paddingRight="16dp"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
|
|
|
@ -1070,4 +1070,31 @@ Puntos</string>
|
|||
<string name="show_arrows_descr">Ver una o dos fleches qu\'indiquen la direición a los marcadores activos.</string>
|
||||
<string name="osmand_parking_am">AM</string>
|
||||
<string name="thank_you_for_feedback">Gracies pola to opinión</string>
|
||||
<string name="search_street">Buscar una rúa</string>
|
||||
<string name="start_search_from_city">Principiar la gueta dende la ciudá</string>
|
||||
<string name="shared_string_restore">Restaurar</string>
|
||||
<string name="keep_passed_markers_descr">Los marcadores añadíos como grupu de Favoritos o puntos de ruta GPX marcaos como Pasaos remanecerán nel mapa. Si\'l grupu nun ta activu, los marcadores desapaecerán del mapa.</string>
|
||||
<string name="keep_passed_markers">Caltener los marcadores pasaos nel mapa</string>
|
||||
<string name="more_transport_on_stop_hint">Hai más tresportes nesta parada.</string>
|
||||
<string name="ask_for_location_permission">Pa siguir fai falta permitir a OsmAnd l\'accesu al allugamientu.</string>
|
||||
<string name="poi_cannot_be_found">Nun pudo alcontrase\'l nodiu o la vía.</string>
|
||||
<string name="search_no_results_feedback">¿Ensin resultaos na gueta?
|
||||
\nComéntanoslo</string>
|
||||
<string name="release_3_2_pre">"• Iguáu el fallu nel aniciu qu\'asocedía colos mapes en caráuteres non llatinos
|
||||
\n
|
||||
\n • Ameyoramientu nos problemes de velocidá de renderizáu nos preseos Android 8.0
|
||||
\n
|
||||
\n • Encontu pa editar oxetos poligonales (non servicios)
|
||||
\n
|
||||
\n • Midir distancies: añadíu\'l botón Midir en Aiciones en el menú contestual "</string>
|
||||
<string name="commiting_way">Unviando vía…</string>
|
||||
<string name="increase_search_radius_to">Aumentar el radiu de gueta a %1$s</string>
|
||||
<string name="send_search_query_description">Unviaremos la consulta de gueta: <b>«%1$s»</b>, asina como l\'allugamientu.<br/><br/> Nun collechamos información personal, sólo necesitamos datos de la gueta p\'ameyorar l\' algoritmu de la mesma.<br/></string>
|
||||
<string name="send_search_query">¿Unviar la consulta de la gueta?</string>
|
||||
<string name="shared_string_world">Mundu</string>
|
||||
<string name="point_deleted">El puntu %1$s desanicióse</string>
|
||||
<string name="coord_input_edit_point">Editar puntu</string>
|
||||
<string name="coord_input_add_point">Añadir un puntu</string>
|
||||
<string name="coord_input_save_as_track">Guardar como traza</string>
|
||||
<string name="coord_input_save_as_track_descr">Añadisti %1$s puntos. Escribe un nome de ficheru y pulsia en «Guardar».</string>
|
||||
</resources>
|
||||
|
|
|
@ -1883,10 +1883,10 @@ Per retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aqu
|
|||
<string name="help_us_to_improve_menu_group">Ajudeu a millorar OsmAnd</string>
|
||||
<string name="other_menu_group">Altres</string>
|
||||
<string name="plugins_menu_group">Connectors</string>
|
||||
<string name="first_usage_item">Primer ús</string>
|
||||
<string name="first_usage_item">Primera utilització</string>
|
||||
<string name="first_usage_item_description">Com baixar mapes i fixar la configuració bàsica.</string>
|
||||
<string name="navigation_item_description">Configuració de la navegació.</string>
|
||||
<string name="planning_trip_item">Planeja un viatge</string>
|
||||
<string name="planning_trip_item">Planificació d\'un viatge</string>
|
||||
<string name="faq_item">PMF</string>
|
||||
<string name="faq_item_description">Preguntes més freqüents</string>
|
||||
<string name="map_viewing_item">Visualització del mapa</string>
|
||||
|
|
|
@ -3783,4 +3783,56 @@
|
|||
<string name="poi_climbing_length">Délka lezení</string>
|
||||
<string name="poi_climbing_length_min">Lezení min. délka</string>
|
||||
<string name="poi_climbing_length_max">Lezení max. délka</string>
|
||||
<string name="poi_climbing_mixed_yes">Smíšené: ano</string>
|
||||
<string name="poi_climbing_mixed_no">Smíšené: ne</string>
|
||||
<string name="poi_climbing_rock_limestone">Lezecká skála: vápenec</string>
|
||||
<string name="poi_climbing_rock_granite">Lezecká skála: žula</string>
|
||||
<string name="poi_climbing_rock_sandstone">Lezecká skála: pískovec</string>
|
||||
<string name="poi_climbing_rock_quartzite">Lezecká skála: křemenec</string>
|
||||
<string name="poi_climbing_rock_gneiss">Lezecká skála: rula</string>
|
||||
<string name="poi_climbing_rock_porphyry">Lezecká skála: porfyr</string>
|
||||
<string name="poi_climbing_quality_solid">Kvalita skály: pevná</string>
|
||||
<string name="poi_climbing_quality_fragile">Kvalita skály: křehká</string>
|
||||
<string name="poi_climbing_orientation_n">Orientace stěny: S</string>
|
||||
<string name="poi_climbing_orientation_ne">Orientace stěny: SV</string>
|
||||
<string name="poi_climbing_orientation_e">Orientace stěny: V</string>
|
||||
<string name="poi_climbing_orientation_se">Orientace stěny: JV</string>
|
||||
<string name="poi_climbing_orientation_s">Orientace stěny: J</string>
|
||||
<string name="poi_climbing_orientation_sw">Orientace stěny: JZ</string>
|
||||
<string name="poi_climbing_orientation_w">Orientace stěny: Z</string>
|
||||
<string name="poi_climbing_orientation_nw">Orientace stěny: SZ</string>
|
||||
<string name="poi_climbing_routes">Lezecké trasy</string>
|
||||
|
||||
<string name="poi_circumference">Obvod</string>
|
||||
<string name="poi_diameter_crown">Průměr koruny</string>
|
||||
|
||||
<string name="poi_meadow_agricultural">Typ: zemědělská</string>
|
||||
<string name="poi_meadow_perpetual">Typ: stálá</string>
|
||||
<string name="poi_meadow_transitional">Typ: přechodná</string>
|
||||
<string name="poi_meadow_pasture">Typ: pastvina</string>
|
||||
|
||||
<string name="poi_frozen_food">Mražené potraviny</string>
|
||||
|
||||
<string name="poi_cannabis">Prodej konopí</string>
|
||||
|
||||
<string name="poi_flooring">Podlahy</string>
|
||||
<string name="poi_pottery">Hrnčířství</string>
|
||||
|
||||
<string name="poi_whitewater_rapid_name">Název peřejí</string>
|
||||
|
||||
<string name="poi_outpost">Výdejna zboží</string>
|
||||
|
||||
<string name="poi_barbecue_grill">Gril: ano</string>
|
||||
|
||||
<string name="poi_amusement_arcade">Herní automaty</string>
|
||||
<string name="poi_adult_gaming_centre">Herna</string>
|
||||
|
||||
<string name="poi_climbing_adventure">Lezecký park</string>
|
||||
|
||||
<string name="poi_via_ferrata">Zajištěná cesta (ferrata)</string>
|
||||
<string name="poi_cable_number">Počet lan</string>
|
||||
<string name="poi_glacier_type_icefall">Ledopád</string>
|
||||
<string name="poi_glacier_type_remnant">Pozůstatek</string>
|
||||
<string name="poi_ruins">Ruiny</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -2967,4 +2967,9 @@ Zobrazená oblast: %1$s x %2$s</string>
|
|||
\n
|
||||
\n• Měření vzdálenosti: tlačítko Měření přidáno do akcí v kontextovém menu
|
||||
\n</string>
|
||||
<string name="search_street">Hledat ulici</string>
|
||||
<string name="start_search_from_city">Začít hledání od města</string>
|
||||
<string name="shared_string_restore">Obnovit</string>
|
||||
<string name="keep_passed_markers_descr">Značky, přidané jako skupina oblíbených nebo GPX bodů a označené jako prošlé, zůstanou na mapě. Pokud skupina není aktivní, značky zmizí z mapy.</string>
|
||||
<string name="keep_passed_markers">Ponechat prošlé značky na mapě</string>
|
||||
</resources>
|
||||
|
|
|
@ -547,7 +547,7 @@
|
|||
<string name="poi_traffic_calming_cushion">Bodenwelle</string>
|
||||
<string name="poi_traffic_calming_hump">Bodenwelle</string>
|
||||
<string name="poi_traffic_calming_rumble_strip">Holperstreifen</string>
|
||||
<string name="poi_traffic_calming_table">Geschwindigkeitstabelle</string>
|
||||
<string name="poi_traffic_calming_table">Bodenwelle</string>
|
||||
<string name="poi_traffic_signals">Ampel</string>
|
||||
<string name="poi_tram_stop">Straßenbahnhaltestelle</string>
|
||||
<string name="poi_travel_agent">Reisebüro</string>
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
<string name="poi_lift_gate">Bariero (levebla)</string>
|
||||
<string name="poi_toll_booth">Vojpagejo</string>
|
||||
<string name="poi_border_control">Landlima kontrolejo</string>
|
||||
<string name="poi_traffic_calming_bump">Stratĝibo kurta</string>
|
||||
<string name="poi_traffic_calming_bump">Stratĝibo mallonga</string>
|
||||
<string name="poi_traffic_calming_hump">Stratĝibo longa</string>
|
||||
<string name="poi_fuel_lpg">Naftogaso likva (LPG)</string>
|
||||
<string name="poi_traffic_calming_cushion">Stratĝibo kusena</string>
|
||||
|
|
|
@ -186,7 +186,7 @@
|
|||
|
||||
<string name="poi_water_well">آب آشامیدنی</string>
|
||||
<string name="poi_standpipe">پایه لوله</string>
|
||||
<string name="poi_water_works">فواره</string>
|
||||
<string name="poi_water_works">سیستم آبرسانی</string>
|
||||
<string name="poi_boatyard">تعمیرگاه قایق</string>
|
||||
<string name="poi_wastewater_plant">کارخانه فاضلابب</string>
|
||||
<string name="poi_water_tower">مخزن آب</string>
|
||||
|
@ -418,7 +418,7 @@
|
|||
<string name="poi_historic_monastery">صومعه تاریخی</string>
|
||||
<string name="poi_wayside_cross"/>
|
||||
<string name="poi_wayside_shrine">زیارتگاه بین راهی</string>
|
||||
<string name="poi_information">اطلاعات گردشگری</string>
|
||||
<string name="poi_information">اطلاعات</string>
|
||||
<string name="poi_clock">ساعت</string>
|
||||
<string name="poi_travel_agent">آژانس مسافرتی</string>
|
||||
<string name="poi_viewpoint">نقشه</string>
|
||||
|
@ -456,7 +456,7 @@
|
|||
<string name="poi_club_photography">کلوپ عکاسی</string>
|
||||
<string name="poi_club_hunting">کلوپ شکار</string>
|
||||
<string name="poi_club_shooting">کلوپ تیراندازی</string>
|
||||
<string name="poi_club_tourism">کلوپ گردشگری</string>
|
||||
<string name="poi_club_tourism">باشگاه گردشگری</string>
|
||||
<string name="poi_club_charity">کلوپ خیریه</string>
|
||||
|
||||
<string name="poi_library">کتابخانه</string>
|
||||
|
@ -696,7 +696,7 @@
|
|||
<string name="poi_resort_type">نوع بازدید</string>
|
||||
<string name="poi_piste_difficulty">سختی پیست</string>
|
||||
<string name="poi_theatre_genre">ژانر تئاتر</string>
|
||||
<string name="poi_fee">قیمت</string>
|
||||
<string name="poi_fee">پولی</string>
|
||||
<string name="poi_recycling_type">نوع</string>
|
||||
<string name="poi_shelter_type">نوع</string>
|
||||
<string name="poi_religion_voodoo">وودو</string>
|
||||
|
@ -745,7 +745,7 @@
|
|||
<string name="poi_access_agricultural">دسترسی کشاورزی</string>
|
||||
|
||||
<string name="poi_aerialway_occupancy">ظرفیت اتاقک/صندلی/ماشین</string>
|
||||
<string name="poi_aerialway_capacity">ظرفیت در ساعت</string>
|
||||
<string name="poi_aerialway_capacity">ظرفیت در هر ساعت</string>
|
||||
<string name="poi_aerialway_duration">متوسط زمان سفر، دقیقه</string>
|
||||
<string name="poi_aerialway_heating_yes">بله</string>
|
||||
<string name="poi_aerialway_heating_no">بدون سیستم گرمایشی</string>
|
||||
|
@ -1113,4 +1113,37 @@
|
|||
<string name="poi_step_condition_uneven">وضعیت پله: ناصاف</string>
|
||||
<string name="poi_step_condition_rough">وضعیت پله: ناهموار</string>
|
||||
|
||||
<string name="poi_supervised_yes">نظارت</string>
|
||||
<string name="poi_supervised_no">بدون نظارت</string>
|
||||
<string name="poi_population">جمعیت</string>
|
||||
<string name="poi_capacity">ظرفیت</string>
|
||||
<string name="poi_capacity_disabled_no">بدون مکان اختصاصی برای ناتوانان جسمی</string>
|
||||
<string name="poi_capacity_disabled">مکان اختصاصی برای ناتوانان جسمی</string>
|
||||
<string name="poi_capacity_women_yes">مکان اختصاصی برای بانوان</string>
|
||||
<string name="poi_capacity_women_no">بدون مکان اختصاصی برای بانوان</string>
|
||||
<string name="poi_capacity_women">مکان اختصاصی برای بانوان</string>
|
||||
<string name="poi_capacity_pupils">مکان اختصاصی برای دانشآموزان</string>
|
||||
<string name="poi_capacity_teachers">مکان اختصاصی برای معلمان</string>
|
||||
<string name="poi_capacity_parent_yes">مکان اختصاصی برای والدین</string>
|
||||
<string name="poi_capacity_parent_no">بدون مکان اختصاصی برای والدین</string>
|
||||
<string name="poi_capacity_parent">مکان اختصاصی برای والدین</string>
|
||||
|
||||
<string name="poi_capacity_beds">ظرفیت (تختها)</string>
|
||||
|
||||
<string name="poi_cuisine">خوراک</string>
|
||||
<string name="poi_cuisine_pizza">پیتزا</string>
|
||||
<string name="poi_cuisine_burger">برگر</string>
|
||||
<string name="poi_cuisine_coffee">قهوه</string>
|
||||
<string name="poi_cuisine_sandwich">ساندویچ</string>
|
||||
<string name="poi_cuisine_kebab">کباب</string>
|
||||
<string name="poi_cuisine_doner">کباب ترکی (شاورما)</string>
|
||||
<string name="poi_cuisine_chicken">جوجه</string>
|
||||
<string name="poi_cuisine_ice_cream">بستنی</string>
|
||||
<string name="poi_cuisine_sushi">سوشی</string>
|
||||
<string name="poi_cuisine_fish_and_chips">ماهی و سیبزمینی سرخشده</string>
|
||||
<string name="poi_cuisine_seafood">غذای دریایی</string>
|
||||
<string name="poi_cuisine_barbecue">کباب سیخی</string>
|
||||
<string name="poi_cuisine_grill">توری</string>
|
||||
<string name="poi_cuisine_tea">چای</string>
|
||||
<string name="poi_cuisine_soup">سوپ</string>
|
||||
</resources>
|
||||
|
|
|
@ -269,7 +269,7 @@
|
|||
<string name="poi_ford_stepping_stones">Stiklubrú</string>
|
||||
<string name="poi_mountain_pass">Fjallaskarð</string>
|
||||
<string name="poi_city_wall">Borgarmúr</string>
|
||||
<string name="poi_traffic_calming_table">Pallur</string>
|
||||
<string name="poi_traffic_calming_table">Hraðahindrun - Pallur</string>
|
||||
<string name="poi_traffic_calming_island">Umferðareyja</string>
|
||||
<string name="poi_traffic_signals">Umferðarljós</string>
|
||||
|
||||
|
@ -1820,7 +1820,7 @@
|
|||
<string name="poi_fire_hydrant">Brunahani</string>
|
||||
<string name="poi_fire_hose">Brunaslanga</string>
|
||||
<string name="poi_ambulance_station">Sjúkrabílastöð</string>
|
||||
<string name="poi_traffic_calming_bump">Ójafna</string>
|
||||
<string name="poi_traffic_calming_bump">Hraðahindrun - Ójafna</string>
|
||||
<string name="poi_car_repair">Bílaviðgerðir</string>
|
||||
<string name="poi_vehicle_inspection">Bifreiðaskoðun</string>
|
||||
<string name="poi_fuel_gtl_diesel">GTL-dísel</string>
|
||||
|
@ -1974,9 +1974,9 @@
|
|||
<string name="poi_public_transport_platform_trolleybus">Biðstöð rafknúinna strætisvagna</string>
|
||||
<string name="poi_railway_platform">Brautarpallur</string>
|
||||
<string name="poi_lift_gate">Bómuhlið</string>
|
||||
<string name="poi_traffic_calming_hump">Alda</string>
|
||||
<string name="poi_traffic_calming_cushion">Koddi</string>
|
||||
<string name="poi_traffic_calming_chicane">Hliðrun</string>
|
||||
<string name="poi_traffic_calming_hump">Hraðahindrun - Alda</string>
|
||||
<string name="poi_traffic_calming_cushion">Hraðahindrun - Koddi</string>
|
||||
<string name="poi_traffic_calming_chicane">Hraðahindrun - Hliðrun</string>
|
||||
<string name="poi_traffic_calming_rumble_strip">Hvinrendur</string>
|
||||
<string name="poi_traffic_calming_choker">Þrenging</string>
|
||||
<string name="poi_railway_buffer_stop">Járnbrautarstuðpúði</string>
|
||||
|
|
|
@ -2975,4 +2975,10 @@ Stendur fyrir svæði: %1$s x %2$s</string>
|
|||
\n
|
||||
\n</string>
|
||||
<string name="rendering_value_black_name">Svart</string>
|
||||
<string name="search_street">Leita að götu</string>
|
||||
<string name="start_search_from_city">Hefja leit út frá borg</string>
|
||||
<string name="shared_string_restore">Endurheimta</string>
|
||||
<string name="keep_passed_markers_descr">Kortamerki sem bætt er inn sem hópi eftirlæta eða sem GPX-ferli og sem þegar hefur verið farið um, verða áfram á kortinu. Ef hópurinn er ekki virkur, munu kortamerkin hverfa.</string>
|
||||
<string name="keep_passed_markers">Halda merkjum sem þegar hefur verið farið um á kortinu</string>
|
||||
<string name="more_transport_on_stop_hint">Það eru fleiri samgöngumátar á þessari biðstöð.</string>
|
||||
</resources>
|
||||
|
|
|
@ -3123,4 +3123,6 @@ Rappresenta l\'area: %1$s x %2$s</string>
|
|||
<string name="shared_string_restore">Ripristina</string>
|
||||
<string name="keep_passed_markers">Tenere passati marcatori sulla mappa</string>
|
||||
<string name="more_transport_on_stop_hint">C\'è più trasporto su questa fermata.</string>
|
||||
<string name="keep_passed_markers_descr">"Marcatori aggiunti come gruppo di favoriti o come punti GPX marcati come Superati rimarranno sulla mappa. Se il gruppo non è attivo i marcatori spariranno dalla mappa "</string>
|
||||
<string name="rendering_value_black_name">Nero</string>
|
||||
</resources>
|
||||
|
|
|
@ -3108,14 +3108,14 @@ Reprezentuje obszar: %1$s x %2$s</string>
|
|||
\n• Inne poprawki błędów
|
||||
\n</string>
|
||||
<string name="increase_search_radius_to">Zwiększ promień wyszukiwania do %1$s</string>
|
||||
<string name="send_search_query_description">Wyślemy twoje zapytanie: <b>\"%1$s\"</b>, oraz twoje położenie.<br/><br/> Nie zbieramy informacji osobistych, potrzebujemy tylko danych wyszukiwania do poprawienia algorytmu wyszukiwania.<br/></string>
|
||||
<string name="send_search_query_description">Zostaną wysłane informacje o zapytaniu: <b>„%1$s”</b> i położeniu.<br/><br/> Informacje osobiste nie są gromadzone. Potrzebne są tylko dane wyszukiwania do poprawienia algorytmu wyszukiwania.<br/></string>
|
||||
<string name="search_no_results_description">Brak wyników?
|
||||
\nPowiedz nam o tym.</string>
|
||||
<string name="send_search_query">Wysłać zapytanie?</string>
|
||||
<string name="shared_string_world">Świat</string>
|
||||
<string name="point_deleted">Usunięto punkt %1$s</string>
|
||||
<string name="thank_you_for_feedback">Dziękuję za opinie</string>
|
||||
<string name="poi_cannot_be_found">Nie można znaleźć węzła lub drogi.</string>
|
||||
<string name="thank_you_for_feedback">Dziękujemy za opinie</string>
|
||||
<string name="poi_cannot_be_found">Nie można odnaleźć węzła lub drogi.</string>
|
||||
<string name="search_no_results_feedback">Brak wyników wyszukiwania?
|
||||
\nPodziel się z nami swoją opinią</string>
|
||||
<string name="commiting_way">Zatwierdzanie drogi…</string>
|
||||
|
@ -3170,14 +3170,17 @@ Reprezentuje obszar: %1$s x %2$s</string>
|
|||
\nOsmAnd jest aktywnie rozwijanym oprogramowaniem typu open source. Każdy może wnieść swój wkład do aplikacji poprzez zgłaszanie błędów, ulepszanie tłumaczeń lub kodowanie nowych funkcji. Dodatkowo projekt opiera się na wkładzie finansowym na finansowanie kodowania i testowania nowych funkcjonalności.
|
||||
\n</string>
|
||||
<string name="test_voice_desrc">Naciśnij przycisk i słuchaj odpowiedniego komunikatu głosowego, aby zidentyfikować brakujące lub błędne monity.</string>
|
||||
<string name="ask_for_location_permission">Zezwól na lokalizację OsmAnd aby kontynuować.</string>
|
||||
<string name="release_3_2_pre">• Naprawiono awarię podczas uruchamiania, która miała miejsce w przypadku map innych niż łacińskie
|
||||
<string name="ask_for_location_permission">Proszę przyznać uprawnienia udostępniania położenia, aby kontynuować.</string>
|
||||
<string name="release_3_2_pre">• Naprawiono awarię podczas uruchamiania, która miała miejsce w przypadku map innych niż łacińskie
|
||||
\n
|
||||
\n• Poprawiono renderowanie na urządzeniach z Androidem 8.0
|
||||
\n• Poprawiono renderowanie na urządzeniach z Androidem 8.0
|
||||
\n
|
||||
\n• Obsługa edycji obiektów wielobokowych (nieoryginalnych)
|
||||
\n
|
||||
\n• Mierz odległość: dodaj przycisk Mierz do akcji w menu kontekstowym
|
||||
\n• Obsługa edycji obiektów wielobocznych (innych niż udogodnienie)
|
||||
\n
|
||||
\n• Mierzenie odległość: dodaj przycisk Mierz do czynności w menu podręcznym
|
||||
\n</string>
|
||||
<string name="rendering_value_black_name">Czarny</string>
|
||||
<string name="shared_string_restore">Przywróć</string>
|
||||
<string name="keep_passed_markers">Zachowanie miniętych znaczników na mapie</string>
|
||||
<string name="more_transport_on_stop_hint">Na tym przystanku zatrzymuje się więcej środków transportu.</string>
|
||||
</resources>
|
||||
|
|
|
@ -3159,4 +3159,9 @@
|
|||
<string name="ask_for_location_permission">請準許 OsmAnd 位置以繼續。</string>
|
||||
<string name="rendering_value_black_name">黑色</string>
|
||||
<string name="more_transport_on_stop_hint">在此停靠站有更多的交通工具。</string>
|
||||
<string name="search_street">搜尋街道</string>
|
||||
<string name="start_search_from_city">從城市開始搜尋</string>
|
||||
<string name="shared_string_restore">還原</string>
|
||||
<string name="keep_passed_markers_descr">標記已加入群組作為我的收藏或 GPX 航點標記為已經過的將維持在地圖上。如果該群組未處於活動狀態,則標記將從地圖上消失。</string>
|
||||
<string name="keep_passed_markers">在地圖上保留已經過的標記</string>
|
||||
</resources>
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Activity;
|
|||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
@ -19,9 +20,10 @@ import net.osmand.plus.OsmandPlugin;
|
|||
import net.osmand.plus.R;
|
||||
|
||||
public class PluginsActivity extends OsmandListActivity {
|
||||
|
||||
public static final int ACTIVE_PLUGINS_LIST_MODIFIED = 1;
|
||||
|
||||
private boolean activePluginsListModified = false;
|
||||
private boolean listModified = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -29,7 +31,6 @@ public class PluginsActivity extends OsmandListActivity {
|
|||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.plugins);
|
||||
getSupportActionBar().setTitle(R.string.plugins_screen);
|
||||
|
||||
setListAdapter(new PluginsListAdapter());
|
||||
}
|
||||
|
||||
|
@ -40,47 +41,40 @@ public class PluginsActivity extends OsmandListActivity {
|
|||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
OsmandPlugin plugin = view.getTag() instanceof OsmandPlugin
|
||||
? (OsmandPlugin)view.getTag()
|
||||
: null;
|
||||
if (plugin == null) {
|
||||
return;
|
||||
Object tag = view.getTag();
|
||||
if (tag instanceof OsmandPlugin) {
|
||||
Intent intent = new Intent(this, PluginActivity.class);
|
||||
intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, ((OsmandPlugin) tag).getId());
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
Intent intent = new Intent(this, PluginActivity.class);
|
||||
intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, plugin.getId());
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void enableDisablePlugin(OsmandPlugin plugin, boolean enable) {
|
||||
boolean ok = OsmandPlugin.enablePlugin(this, ((OsmandApplication) getApplication()), plugin,
|
||||
enable);
|
||||
if (!ok) {
|
||||
return;
|
||||
OsmandApplication app = (OsmandApplication) getApplication();
|
||||
if (OsmandPlugin.enablePlugin(this, app, plugin, enable)) {
|
||||
if (!listModified) {
|
||||
setResult(ACTIVE_PLUGINS_LIST_MODIFIED);
|
||||
listModified = true;
|
||||
}
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
if (!activePluginsListModified) {
|
||||
setResult(ACTIVE_PLUGINS_LIST_MODIFIED);
|
||||
activePluginsListModified = true;
|
||||
}
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
protected class PluginsListAdapter extends ArrayAdapter<OsmandPlugin> {
|
||||
public PluginsListAdapter() {
|
||||
super(PluginsActivity.this, R.layout.plugins_list_item,
|
||||
OsmandPlugin.getVisiblePlugins());
|
||||
|
||||
PluginsListAdapter() {
|
||||
super(PluginsActivity.this, R.layout.plugins_list_item, OsmandPlugin.getVisiblePlugins());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = getLayoutInflater().inflate(R.layout.plugins_list_item, parent, false);
|
||||
|
@ -90,14 +84,14 @@ public class PluginsActivity extends OsmandListActivity {
|
|||
|
||||
view.setTag(plugin);
|
||||
|
||||
ImageButton pluginLogo = (ImageButton)view.findViewById(R.id.plugin_logo);
|
||||
ImageButton pluginLogo = (ImageButton) view.findViewById(R.id.plugin_logo);
|
||||
pluginLogo.setImageResource(plugin.getLogoResourceId());
|
||||
if (plugin.isActive()) {
|
||||
pluginLogo.setBackgroundResource(R.drawable.bg_plugin_logo_enabled);
|
||||
pluginLogo.setContentDescription(getString(R.string.shared_string_disable));
|
||||
} else {
|
||||
TypedArray attributes = getTheme().obtainStyledAttributes(
|
||||
new int[] {R.attr.bg_plugin_logo_disabled});
|
||||
new int[]{R.attr.bg_plugin_logo_disabled});
|
||||
pluginLogo.setBackgroundDrawable(attributes.getDrawable(0));
|
||||
pluginLogo.setContentDescription(getString(plugin.needsInstallation() ? R.string.access_shared_string_not_installed : R.string.shared_string_enable));
|
||||
attributes.recycle();
|
||||
|
@ -105,7 +99,7 @@ public class PluginsActivity extends OsmandListActivity {
|
|||
pluginLogo.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(!plugin.isActive() && plugin.needsInstallation()) {
|
||||
if (!plugin.isActive() && plugin.needsInstallation()) {
|
||||
// nothing
|
||||
} else {
|
||||
enableDisablePlugin(plugin, !plugin.isActive());
|
||||
|
@ -113,16 +107,15 @@ public class PluginsActivity extends OsmandListActivity {
|
|||
}
|
||||
});
|
||||
|
||||
TextView pluginName = (TextView)view.findViewById(R.id.plugin_name);
|
||||
TextView pluginName = (TextView) view.findViewById(R.id.plugin_name);
|
||||
pluginName.setText(plugin.getName());
|
||||
pluginName.setContentDescription(plugin.getName() + " " + getString(plugin.isActive()
|
||||
? R.string.item_checked
|
||||
: R.string.item_unchecked));
|
||||
|
||||
TextView pluginDescription = (TextView)view.findViewById(R.id.plugin_description);
|
||||
TextView pluginDescription = (TextView) view.findViewById(R.id.plugin_description);
|
||||
pluginDescription.setText(plugin.getDescription());
|
||||
|
||||
|
||||
ImageView pluginOptions = (ImageView) view.findViewById(R.id.plugin_options);
|
||||
pluginOptions.setImageDrawable(getMyApplication().getUIUtilities().getThemedIcon(R.drawable.ic_overflow_menu_white));
|
||||
pluginOptions.setOnClickListener(new View.OnClickListener() {
|
||||
|
|
|
@ -45,15 +45,12 @@ public class SearchHistoryHelper {
|
|||
}
|
||||
|
||||
public void addNewItemToHistory(AbstractPoiType pt) {
|
||||
PointDescription pd = new PointDescription(PointDescription.POINT_TYPE_POI_TYPE, pt.getKeyName());
|
||||
addNewItemToHistory(new HistoryEntry(0, 0, pd));
|
||||
addNewItemToHistory(new HistoryEntry(0, 0, createPointDescription(pt)));
|
||||
}
|
||||
|
||||
public void addNewItemToHistory(PoiUIFilter filter) {
|
||||
String filterId = filter.getFilterId();
|
||||
PointDescription pd = new PointDescription(PointDescription.POINT_TYPE_CUSTOM_POI_FILTER, filterId);
|
||||
addNewItemToHistory(new HistoryEntry(0, 0, pd));
|
||||
context.getPoiFilters().markHistory(filterId, true);
|
||||
addNewItemToHistory(new HistoryEntry(0, 0, createPointDescription(filter)));
|
||||
context.getPoiFilters().markHistory(filter.getFilterId(), true);
|
||||
}
|
||||
|
||||
public List<HistoryEntry> getHistoryEntries(boolean onlyPoints) {
|
||||
|
@ -70,15 +67,36 @@ public class SearchHistoryHelper {
|
|||
return res;
|
||||
}
|
||||
|
||||
public void remove(HistoryEntry model) {
|
||||
HistoryItemDBHelper helper = checkLoadedEntries();
|
||||
if (helper.remove(model)) {
|
||||
PointDescription pd = model.getName();
|
||||
private PointDescription createPointDescription(AbstractPoiType pt) {
|
||||
return new PointDescription(PointDescription.POINT_TYPE_POI_TYPE, pt.getKeyName());
|
||||
}
|
||||
|
||||
private PointDescription createPointDescription(PoiUIFilter filter) {
|
||||
return new PointDescription(PointDescription.POINT_TYPE_CUSTOM_POI_FILTER, filter.getFilterId());
|
||||
}
|
||||
|
||||
public void remove(Object item) {
|
||||
PointDescription pd = null;
|
||||
if (item instanceof HistoryEntry) {
|
||||
pd = ((HistoryEntry) item).getName();
|
||||
} else if (item instanceof AbstractPoiType) {
|
||||
pd = createPointDescription((AbstractPoiType) item);
|
||||
} else if (item instanceof PoiUIFilter) {
|
||||
pd = createPointDescription((PoiUIFilter) item);
|
||||
}
|
||||
if (pd != null) {
|
||||
remove(pd);
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(PointDescription pd) {
|
||||
HistoryEntry model = mp.get(pd);
|
||||
if (model != null && checkLoadedEntries().remove(model)) {
|
||||
if (pd.isCustomPoiFilter()) {
|
||||
context.getPoiFilters().markHistory(pd.getName(), false);
|
||||
}
|
||||
loadedEntries.remove(model);
|
||||
mp.remove(model.getName());
|
||||
mp.remove(pd);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -509,15 +509,29 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter>
|
|||
|
||||
public String getTypesName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (PoiCategory p : acceptedTypes.keySet()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(", ");
|
||||
for (Map.Entry<PoiCategory, LinkedHashSet<String>> entry : acceptedTypes.entrySet()) {
|
||||
LinkedHashSet<String> set = entry.getValue();
|
||||
if (set != null && !set.isEmpty()) {
|
||||
for (String key : set) {
|
||||
PoiType pt = poiTypes.getPoiTypeByKey(key);
|
||||
if (pt != null) {
|
||||
appendWithSeparator(sb, pt.getTranslation());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appendWithSeparator(sb, entry.getKey().getTranslation());
|
||||
}
|
||||
sb.append(p.getTranslation());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void appendWithSeparator(StringBuilder sb, String s) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* @return null if all subtypes are accepted/ empty list if type is not accepted at all
|
||||
|
|
|
@ -342,6 +342,13 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
|||
filter = app.getPoiFilters().getNominatimPOIFilter();
|
||||
filter.setFilterByName(searchPhrase.getUnknownSearchPhrase());
|
||||
filter.clearCurrentResults();
|
||||
} else if (searchPhrase.hasUnknownSearchWordPoiType()) {
|
||||
AbstractPoiType pt = searchPhrase.getUnknownSearchWordPoiType();
|
||||
filter = new PoiUIFilter(pt, app, "");
|
||||
String customName = searchPhrase.getPoiNameFilter();
|
||||
if (!Algorithms.isEmpty(customName)) {
|
||||
filter.setFilterByName(customName);
|
||||
}
|
||||
} else {
|
||||
filter = app.getPoiFilters().getSearchByNamePOIFilter();
|
||||
if (!Algorithms.isEmpty(searchPhrase.getUnknownSearchWord())) {
|
||||
|
@ -2370,8 +2377,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
|||
QuickSearchDialogFragment parentFragment = (QuickSearchDialogFragment) getParentFragment();
|
||||
SearchHistoryHelper helper = SearchHistoryHelper.getInstance(parentFragment.getMyApplication());
|
||||
for (QuickSearchListItem searchListItem : selectedItems) {
|
||||
HistoryEntry historyEntry = (HistoryEntry) searchListItem.getSearchResult().object;
|
||||
helper.remove(historyEntry);
|
||||
helper.remove(searchListItem.getSearchResult().object);
|
||||
}
|
||||
parentFragment.reloadHistory();
|
||||
parentFragment.enableSelectionMode(false, -1);
|
||||
|
|
Loading…
Reference in a new issue