refactoring and fixes
This commit is contained in:
parent
42a7a5d88d
commit
576c4330b4
9 changed files with 68 additions and 58 deletions
|
@ -691,31 +691,21 @@ public class OsmandRegions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WorldRegion> getWoldRegionsAt(LatLon latLon) throws IOException {
|
public List<WorldRegion> getWorldRegionsAt(LatLon latLon) throws IOException {
|
||||||
List<WorldRegion> result = new ArrayList<>();
|
Map<WorldRegion, BinaryMapDataObject> mapDataObjects = getBinaryMapDataObjectsWithRegionsAt(latLon);
|
||||||
List<BinaryMapDataObject> mapDataObjects = getBinaryMapDataObjectsAt(latLon);
|
return new ArrayList<>(mapDataObjects.keySet());
|
||||||
for (BinaryMapDataObject obj : mapDataObjects) {
|
|
||||||
String fullName = getFullName(obj);
|
|
||||||
if (fullName != null) {
|
|
||||||
WorldRegion reg = getRegionData(fullName);
|
|
||||||
if (reg != null) {
|
|
||||||
result.add(reg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BinaryMapDataObject getSmallestBinaryMapDataObjectAt(LatLon latLon) throws IOException {
|
public Map.Entry<WorldRegion, BinaryMapDataObject> getSmallestBinaryMapDataObjectAt(LatLon latLon) throws IOException {
|
||||||
List<BinaryMapDataObject> mapDataObjects = getBinaryMapDataObjectsAt(latLon);
|
Map<WorldRegion, BinaryMapDataObject> mapDataObjectsWithRegions = getBinaryMapDataObjectsWithRegionsAt(latLon);
|
||||||
return getSmallestBinaryMapDataObjectAt(mapDataObjects);
|
return getSmallestBinaryMapDataObjectAt(mapDataObjectsWithRegions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BinaryMapDataObject getSmallestBinaryMapDataObjectAt(List<BinaryMapDataObject> mapDataObjects) {
|
public Map.Entry<WorldRegion, BinaryMapDataObject> getSmallestBinaryMapDataObjectAt(Map<WorldRegion, BinaryMapDataObject> mapDataObjectsWithRegions) {
|
||||||
BinaryMapDataObject res = null;
|
Map.Entry<WorldRegion, BinaryMapDataObject> res = null;
|
||||||
double smallestArea = -1;
|
double smallestArea = -1;
|
||||||
for (BinaryMapDataObject o : mapDataObjects) {
|
for (Map.Entry<WorldRegion, BinaryMapDataObject> o : mapDataObjectsWithRegions.entrySet()) {
|
||||||
double area = OsmandRegions.getArea(o);
|
double area = OsmandRegions.getArea(o.getValue());
|
||||||
if (smallestArea == -1) {
|
if (smallestArea == -1) {
|
||||||
smallestArea = area;
|
smallestArea = area;
|
||||||
res = o;
|
res = o;
|
||||||
|
@ -727,10 +717,10 @@ public class OsmandRegions {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BinaryMapDataObject> getBinaryMapDataObjectsAt(LatLon latLon) throws IOException {
|
private Map<WorldRegion, BinaryMapDataObject> getBinaryMapDataObjectsWithRegionsAt(LatLon latLon) throws IOException {
|
||||||
int point31x = MapUtils.get31TileNumberX(latLon.getLongitude());
|
int point31x = MapUtils.get31TileNumberX(latLon.getLongitude());
|
||||||
int point31y = MapUtils.get31TileNumberY(latLon.getLatitude());
|
int point31y = MapUtils.get31TileNumberY(latLon.getLatitude());
|
||||||
|
Map<WorldRegion, BinaryMapDataObject> foundObjects = new LinkedHashMap<>();
|
||||||
List<BinaryMapDataObject> mapDataObjects;
|
List<BinaryMapDataObject> mapDataObjects;
|
||||||
try {
|
try {
|
||||||
mapDataObjects = queryBboxNoInit(point31x, point31x, point31y, point31y, true);
|
mapDataObjects = queryBboxNoInit(point31x, point31x, point31y, point31y, true);
|
||||||
|
@ -748,11 +738,13 @@ public class OsmandRegions {
|
||||||
|| !downloadRegion.isRegionMapDownload()
|
|| !downloadRegion.isRegionMapDownload()
|
||||||
|| !contain(o, point31x, point31y)) {
|
|| !contain(o, point31x, point31y)) {
|
||||||
it.remove();
|
it.remove();
|
||||||
|
} else {
|
||||||
|
foundObjects.put(downloadRegion, o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mapDataObjects;
|
return foundObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1342,6 +1342,29 @@ public class OsmandSettings {
|
||||||
public final OsmandPreference<AngularConstants> ANGULAR_UNITS = new EnumIntPreference<AngularConstants>(
|
public final OsmandPreference<AngularConstants> ANGULAR_UNITS = new EnumIntPreference<AngularConstants>(
|
||||||
"angular_measurement", AngularConstants.DEGREES, AngularConstants.values()).makeProfile();
|
"angular_measurement", AngularConstants.DEGREES, AngularConstants.values()).makeProfile();
|
||||||
|
|
||||||
|
public static final String LAST_START_LAT = "last_searched_lat"; //$NON-NLS-1$
|
||||||
|
public static final String LAST_START_LON = "last_searched_lon"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public LatLon getLastStartPoint() {
|
||||||
|
if (settingsAPI.contains(globalPreferences, LAST_START_LAT) && settingsAPI.contains(globalPreferences, LAST_START_LON)) {
|
||||||
|
return new LatLon(settingsAPI.getFloat(globalPreferences, LAST_START_LAT, 0),
|
||||||
|
settingsAPI.getFloat(globalPreferences, LAST_START_LON, 0));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setLastStartPoint(LatLon l) {
|
||||||
|
if (l == null) {
|
||||||
|
return settingsAPI.edit(globalPreferences).remove(LAST_START_LAT).remove(LAST_START_LON).commit();
|
||||||
|
} else {
|
||||||
|
return setLastStartPoint(l.getLatitude(), l.getLongitude());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setLastStartPoint(double lat, double lon) {
|
||||||
|
return settingsAPI.edit(globalPreferences).putFloat(LAST_START_LAT, (float) lat).
|
||||||
|
putFloat(LAST_START_LON, (float) lon).commit();
|
||||||
|
}
|
||||||
|
|
||||||
public final OsmandPreference<SpeedConstants> SPEED_SYSTEM = new EnumIntPreference<SpeedConstants>(
|
public final OsmandPreference<SpeedConstants> SPEED_SYSTEM = new EnumIntPreference<SpeedConstants>(
|
||||||
"default_speed_system", SpeedConstants.KILOMETERS_PER_HOUR, SpeedConstants.values()) {
|
"default_speed_system", SpeedConstants.KILOMETERS_PER_HOUR, SpeedConstants.values()) {
|
||||||
|
|
|
@ -445,6 +445,7 @@ public class TargetPointsHelper {
|
||||||
Location lastKnownLocation = ctx.getLocationProvider().getLastKnownLocation();
|
Location lastKnownLocation = ctx.getLocationProvider().getLastKnownLocation();
|
||||||
LatLon latLon = lastKnownLocation != null ?
|
LatLon latLon = lastKnownLocation != null ?
|
||||||
new LatLon(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()) : null;
|
new LatLon(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()) : null;
|
||||||
|
routingHelper.checkAndUpdateStartLocation(latLon);
|
||||||
setMyLocationPoint(latLon, false, null);
|
setMyLocationPoint(latLon, false, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import android.view.WindowManager;
|
||||||
|
|
||||||
import net.osmand.Location;
|
import net.osmand.Location;
|
||||||
import net.osmand.StateChangedListener;
|
import net.osmand.StateChangedListener;
|
||||||
import net.osmand.binary.BinaryMapDataObject;
|
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.RotatedTileBox;
|
import net.osmand.data.RotatedTileBox;
|
||||||
import net.osmand.map.IMapLocationListener;
|
import net.osmand.map.IMapLocationListener;
|
||||||
|
@ -28,6 +27,7 @@ import net.osmand.plus.views.AnimateDraggingMapThread;
|
||||||
import net.osmand.plus.views.OsmandMapTileView;
|
import net.osmand.plus.views.OsmandMapTileView;
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc
|
||||||
locationProvider = location.getProvider();
|
locationProvider = location.getProvider();
|
||||||
if (settings.DRIVING_REGION_AUTOMATIC.get() && !drivingRegionUpdated && !app.isApplicationInitializing()) {
|
if (settings.DRIVING_REGION_AUTOMATIC.get() && !drivingRegionUpdated && !app.isApplicationInitializing()) {
|
||||||
drivingRegionUpdated = true;
|
drivingRegionUpdated = true;
|
||||||
app.getRoutingHelper().cacheStartLocation(location);
|
app.getRoutingHelper().checkAndUpdateStartLocation(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mapView != null) {
|
if (mapView != null) {
|
||||||
|
@ -444,7 +444,7 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc
|
||||||
isUserZoomed = true;
|
isUserZoomed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DetectDrivingRegionTask extends AsyncTask<LatLon, Void, BinaryMapDataObject> {
|
private static class DetectDrivingRegionTask extends AsyncTask<LatLon, Void, WorldRegion> {
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
|
|
||||||
|
@ -453,10 +453,10 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BinaryMapDataObject doInBackground(LatLon... latLons) {
|
protected WorldRegion doInBackground(LatLon... latLons) {
|
||||||
try {
|
try {
|
||||||
if (latLons != null && latLons.length > 0) {
|
if (latLons != null && latLons.length > 0) {
|
||||||
return app.getRegions().getSmallestBinaryMapDataObjectAt(latLons[0]);
|
return app.getRegions().getSmallestBinaryMapDataObjectAt(latLons[0]).getKey();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// ignore
|
// ignore
|
||||||
|
@ -465,14 +465,10 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(BinaryMapDataObject o) {
|
protected void onPostExecute(WorldRegion worldRegion) {
|
||||||
if (o != null) {
|
|
||||||
String fullName = app.getRegions().getFullName(o);
|
|
||||||
WorldRegion worldRegion = app.getRegions().getRegionData(fullName);
|
|
||||||
if (worldRegion != null) {
|
if (worldRegion != null) {
|
||||||
app.setupDrivingRegion(worldRegion);
|
app.setupDrivingRegion(worldRegion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,7 +468,7 @@ public class DownloadResources extends DownloadResourceGroup {
|
||||||
List<IndexItem> res = new ArrayList<>();
|
List<IndexItem> res = new ArrayList<>();
|
||||||
OsmandRegions regions = app.getRegions();
|
OsmandRegions regions = app.getRegions();
|
||||||
DownloadIndexesThread downloadThread = app.getDownloadThread();
|
DownloadIndexesThread downloadThread = app.getDownloadThread();
|
||||||
List<WorldRegion> downloadRegions = regions.getWoldRegionsAt(latLon);
|
List<WorldRegion> downloadRegions = regions.getWorldRegionsAt(latLon);
|
||||||
for (WorldRegion downloadRegion : downloadRegions) {
|
for (WorldRegion downloadRegion : downloadRegions) {
|
||||||
if (includeDownloaded || !isIndexItemDownloaded(downloadThread, type, downloadRegion, res)) {
|
if (includeDownloaded || !isIndexItemDownloaded(downloadThread, type, downloadRegion, res)) {
|
||||||
addIndexItem(downloadThread, type, downloadRegion, res);
|
addIndexItem(downloadThread, type, downloadRegion, res);
|
||||||
|
|
|
@ -417,14 +417,13 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
|
||||||
protected IndexItem doInBackground(Void... params) {
|
protected IndexItem doInBackground(Void... params) {
|
||||||
Amenity amenity = cityItem.getAmenity();
|
Amenity amenity = cityItem.getAmenity();
|
||||||
BinaryMapDataObject o = null;
|
BinaryMapDataObject o = null;
|
||||||
|
WorldRegion downloadRegion = null;
|
||||||
try {
|
try {
|
||||||
o = osmandRegions.getSmallestBinaryMapDataObjectAt(amenity.getLocation());
|
downloadRegion = osmandRegions.getSmallestBinaryMapDataObjectAt(amenity.getLocation()).getKey();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
if (o != null) {
|
if (downloadRegion != null) {
|
||||||
String selectedFullName = osmandRegions.getFullName(o);
|
|
||||||
WorldRegion downloadRegion = osmandRegions.getRegionData(selectedFullName);
|
|
||||||
List<IndexItem> indexItems = ctx.getDownloadThread().getIndexes().getIndexItems(downloadRegion);
|
List<IndexItem> indexItems = ctx.getDownloadThread().getIndexes().getIndexItems(downloadRegion);
|
||||||
for (IndexItem item : indexItems) {
|
for (IndexItem item : indexItems) {
|
||||||
if (item.getType() == DownloadActivityType.NORMAL_FILE) {
|
if (item.getType() == DownloadActivityType.NORMAL_FILE) {
|
||||||
|
|
|
@ -39,6 +39,7 @@ public class RoutingHelper {
|
||||||
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RoutingHelper.class);
|
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RoutingHelper.class);
|
||||||
|
|
||||||
private static final float POSITION_TOLERANCE = 60;
|
private static final float POSITION_TOLERANCE = 60;
|
||||||
|
private static final int CACHE_RADIUS = 100000;
|
||||||
|
|
||||||
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
|
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
|
||||||
private List<WeakReference<IRoutingDataUpdateListener>> updateListeners = new LinkedList<>();
|
private List<WeakReference<IRoutingDataUpdateListener>> updateListeners = new LinkedList<>();
|
||||||
|
@ -57,7 +58,6 @@ public class RoutingHelper {
|
||||||
private List<LatLon> intermediatePoints;
|
private List<LatLon> intermediatePoints;
|
||||||
private Location lastProjection;
|
private Location lastProjection;
|
||||||
private Location lastFixedLocation;
|
private Location lastFixedLocation;
|
||||||
private LatLon lastStartLocation = null;
|
|
||||||
|
|
||||||
private static final int RECALCULATE_THRESHOLD_COUNT_CAUSING_FULL_RECALCULATE = 3;
|
private static final int RECALCULATE_THRESHOLD_COUNT_CAUSING_FULL_RECALCULATE = 3;
|
||||||
private static final int RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL = 2*60*1000;
|
private static final int RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL = 2*60*1000;
|
||||||
|
@ -174,8 +174,8 @@ public class RoutingHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation){
|
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation){
|
||||||
|
checkAndUpdateStartLocation(currentLocation);
|
||||||
RouteCalculationResult previousRoute = route;
|
RouteCalculationResult previousRoute = route;
|
||||||
cacheStartLocation(currentLocation);
|
|
||||||
clearCurrentRoute(finalLocation, intermediatePoints);
|
clearCurrentRoute(finalLocation, intermediatePoints);
|
||||||
// to update route
|
// to update route
|
||||||
setCurrentLocation(currentLocation, false, previousRoute, true);
|
setCurrentLocation(currentLocation, false, previousRoute, true);
|
||||||
|
@ -261,15 +261,15 @@ public class RoutingHelper {
|
||||||
public LatLon getFinalLocation() {
|
public LatLon getFinalLocation() {
|
||||||
return finalLocation;
|
return finalLocation;
|
||||||
}
|
}
|
||||||
|
public void checkAndUpdateStartLocation(Location nextStartLocation) {
|
||||||
|
checkAndUpdateStartLocation(new LatLon(nextStartLocation.getLatitude(), nextStartLocation.getLongitude()));
|
||||||
|
}
|
||||||
|
|
||||||
public void cacheStartLocation(Location nextStartLocation) {
|
public void checkAndUpdateStartLocation(LatLon newStartLocation) {
|
||||||
LatLon start = new LatLon(nextStartLocation.getLatitude(), nextStartLocation.getLongitude());
|
LatLon lastStartLocation = app.getSettings().getLastStartPoint();
|
||||||
if (lastStartLocation == null) {
|
if (lastStartLocation == null || MapUtils.getDistance(newStartLocation, lastStartLocation) > CACHE_RADIUS) {
|
||||||
lastStartLocation = new LatLon(nextStartLocation.getLatitude(), nextStartLocation.getLongitude());
|
app.getMapViewTrackingUtilities().detectDrivingRegion(newStartLocation);
|
||||||
app.getMapViewTrackingUtilities().detectDrivingRegion(lastStartLocation);
|
app.getSettings().setLastStartPoint(newStartLocation);
|
||||||
} else if (MapUtils.getDistance(start, lastStartLocation) > 100000) {
|
|
||||||
lastStartLocation = start;
|
|
||||||
app.getMapViewTrackingUtilities().detectDrivingRegion(lastStartLocation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,10 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@ -250,7 +252,7 @@ public class DownloadedRegionsLayer extends OsmandMapLayer implements IContextMe
|
||||||
&& zoom >= ZOOM_MIN_TO_SHOW_DOWNLOAD_DIALOG && zoom <= ZOOM_MAX_TO_SHOW_DOWNLOAD_DIALOG
|
&& zoom >= ZOOM_MIN_TO_SHOW_DOWNLOAD_DIALOG && zoom <= ZOOM_MAX_TO_SHOW_DOWNLOAD_DIALOG
|
||||||
&& currentObjects != null) {
|
&& currentObjects != null) {
|
||||||
WorldRegion regionData;
|
WorldRegion regionData;
|
||||||
List<BinaryMapDataObject> selectedObjects = new ArrayList<>();
|
Map<WorldRegion, BinaryMapDataObject> selectedObjects = new LinkedHashMap<>();
|
||||||
for (int i = 0; i < currentObjects.size(); i++) {
|
for (int i = 0; i < currentObjects.size(); i++) {
|
||||||
final BinaryMapDataObject o = currentObjects.get(i);
|
final BinaryMapDataObject o = currentObjects.get(i);
|
||||||
String fullName = osmandRegions.getFullName(o);
|
String fullName = osmandRegions.getFullName(o);
|
||||||
|
@ -262,7 +264,7 @@ public class DownloadedRegionsLayer extends OsmandMapLayer implements IContextMe
|
||||||
hideDownloadMapToolbar();
|
hideDownloadMapToolbar();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
selectedObjects.add(o);
|
selectedObjects.put(regionData, o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,11 +272,8 @@ public class DownloadedRegionsLayer extends OsmandMapLayer implements IContextMe
|
||||||
|
|
||||||
IndexItem indexItem = null;
|
IndexItem indexItem = null;
|
||||||
String name = null;
|
String name = null;
|
||||||
BinaryMapDataObject smallestRegion = app.getRegions().getSmallestBinaryMapDataObjectAt(selectedObjects);
|
regionData = app.getRegions().getSmallestBinaryMapDataObjectAt(selectedObjects).getKey();
|
||||||
if (smallestRegion != null) {
|
if (regionData != null) {
|
||||||
String fullName = osmandRegions.getFullName(smallestRegion);
|
|
||||||
regionData = osmandRegions.getRegionData(fullName);
|
|
||||||
|
|
||||||
DownloadIndexesThread downloadThread = app.getDownloadThread();
|
DownloadIndexesThread downloadThread = app.getDownloadThread();
|
||||||
List<IndexItem> indexItems = downloadThread.getIndexes().getIndexItems(regionData);
|
List<IndexItem> indexItems = downloadThread.getIndexes().getIndexItems(regionData);
|
||||||
if (indexItems.size() == 0) {
|
if (indexItems.size() == 0) {
|
||||||
|
|
|
@ -107,7 +107,7 @@ public class WikiArticleHelper {
|
||||||
List<WorldRegion> regions = null;
|
List<WorldRegion> regions = null;
|
||||||
if (articleLatLon != null) {
|
if (articleLatLon != null) {
|
||||||
try {
|
try {
|
||||||
regions = application.getRegions().getWoldRegionsAt(articleLatLon);
|
regions = application.getRegions().getWorldRegionsAt(articleLatLon);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, e.getMessage(), e);
|
Log.e(TAG, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue