Add api method to subscribe for updates on next turn type and distance via callback.
This commit is contained in:
parent
f5b015d501
commit
d014c7a841
10 changed files with 255 additions and 3 deletions
|
@ -2,6 +2,7 @@ package net.osmand.aidl;
|
||||||
|
|
||||||
import net.osmand.aidl.search.SearchResult;
|
import net.osmand.aidl.search.SearchResult;
|
||||||
import net.osmand.aidl.gpx.AGpxBitmap;
|
import net.osmand.aidl.gpx.AGpxBitmap;
|
||||||
|
import net.osmand.aidl.navigation.ADirectionInfo;
|
||||||
|
|
||||||
interface IOsmAndAidlCallback {
|
interface IOsmAndAidlCallback {
|
||||||
void onSearchComplete(in List<SearchResult> resultSet);
|
void onSearchComplete(in List<SearchResult> resultSet);
|
||||||
|
@ -11,4 +12,6 @@ interface IOsmAndAidlCallback {
|
||||||
void onAppInitialized();
|
void onAppInitialized();
|
||||||
|
|
||||||
void onGpxBitmapCreated(in AGpxBitmap bitmap);
|
void onGpxBitmapCreated(in AGpxBitmap bitmap);
|
||||||
|
|
||||||
|
void updateNavigationInfo(in ADirectionInfo directionInfo);
|
||||||
}
|
}
|
|
@ -81,7 +81,7 @@ import net.osmand.aidl.tiles.ASqliteDbFile;
|
||||||
import net.osmand.aidl.plugins.PluginParams;
|
import net.osmand.aidl.plugins.PluginParams;
|
||||||
import net.osmand.aidl.copyfile.CopyFileParams;
|
import net.osmand.aidl.copyfile.CopyFileParams;
|
||||||
|
|
||||||
|
import net.osmand.aidl.navigation.ANavigationUpdateParams;
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Add new methods at the end of file!!!
|
// NOTE: Add new methods at the end of file!!!
|
||||||
|
@ -182,4 +182,6 @@ interface IOsmAndAidlInterface {
|
||||||
boolean getBitmapForGpx(in CreateGpxBitmapParams file, IOsmAndAidlCallback callback);
|
boolean getBitmapForGpx(in CreateGpxBitmapParams file, IOsmAndAidlCallback callback);
|
||||||
|
|
||||||
int copyFile(in CopyFileParams filePart);
|
int copyFile(in CopyFileParams filePart);
|
||||||
|
|
||||||
|
long registerForNavigationUpdates(in ANavigationUpdateParams params, IOsmAndAidlCallback callback);
|
||||||
}
|
}
|
|
@ -42,6 +42,8 @@ import net.osmand.aidl.maplayer.point.AMapPoint;
|
||||||
import net.osmand.aidl.mapmarker.AMapMarker;
|
import net.osmand.aidl.mapmarker.AMapMarker;
|
||||||
import net.osmand.aidl.mapwidget.AMapWidget;
|
import net.osmand.aidl.mapwidget.AMapWidget;
|
||||||
import net.osmand.aidl.navdrawer.NavDrawerFooterParams;
|
import net.osmand.aidl.navdrawer.NavDrawerFooterParams;
|
||||||
|
import net.osmand.aidl.navigation.ADirectionInfo;
|
||||||
|
import net.osmand.aidl.navigation.ANavigationUpdateParams;
|
||||||
import net.osmand.aidl.plugins.PluginParams;
|
import net.osmand.aidl.plugins.PluginParams;
|
||||||
import net.osmand.aidl.search.SearchResult;
|
import net.osmand.aidl.search.SearchResult;
|
||||||
import net.osmand.aidl.tiles.ASqliteDbFile;
|
import net.osmand.aidl.tiles.ASqliteDbFile;
|
||||||
|
@ -75,6 +77,7 @@ import net.osmand.plus.helpers.ExternalApiHelper;
|
||||||
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
|
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
|
||||||
import net.osmand.plus.myplaces.TrackBitmapDrawer;
|
import net.osmand.plus.myplaces.TrackBitmapDrawer;
|
||||||
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
|
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
|
||||||
|
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||||
import net.osmand.plus.routing.RoutingHelper;
|
import net.osmand.plus.routing.RoutingHelper;
|
||||||
import net.osmand.plus.views.AidlMapLayer;
|
import net.osmand.plus.views.AidlMapLayer;
|
||||||
import net.osmand.plus.views.MapInfoLayer;
|
import net.osmand.plus.views.MapInfoLayer;
|
||||||
|
@ -83,6 +86,7 @@ import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
|
||||||
import net.osmand.plus.views.OsmandMapTileView;
|
import net.osmand.plus.views.OsmandMapTileView;
|
||||||
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo;
|
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo;
|
||||||
import net.osmand.plus.views.mapwidgets.TextInfoWidget;
|
import net.osmand.plus.views.mapwidgets.TextInfoWidget;
|
||||||
|
import net.osmand.router.TurnType;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -191,6 +195,9 @@ public class OsmandAidlApi {
|
||||||
|
|
||||||
private boolean mapActivityActive = false;
|
private boolean mapActivityActive = false;
|
||||||
|
|
||||||
|
private Map<Long, IOsmAndAidlCallback> callbacks;
|
||||||
|
private long updateCallbackId = 0;
|
||||||
|
|
||||||
public OsmandAidlApi(OsmandApplication app) {
|
public OsmandAidlApi(OsmandApplication app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
loadConnectedApps();
|
loadConnectedApps();
|
||||||
|
@ -238,6 +245,12 @@ public class OsmandAidlApi {
|
||||||
receivers = new TreeMap<>();
|
receivers = new TreeMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isAidlSubscribedForUpdates() {
|
||||||
|
// return !callbacks.isEmpty();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isUpdateAllowed() {
|
public boolean isUpdateAllowed() {
|
||||||
return mapActivityActive;
|
return mapActivityActive;
|
||||||
}
|
}
|
||||||
|
@ -1918,6 +1931,57 @@ public class OsmandAidlApi {
|
||||||
return app.getAppCustomization().changePluginStatus(params);
|
return app.getAppCustomization().changePluginStatus(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long registerForNavigationUpdates(ANavigationUpdateParams params, IOsmAndAidlCallback callback) {
|
||||||
|
if (params.isSubscribeToUpdates()) {
|
||||||
|
updateCallbackId++;
|
||||||
|
callbacks.put(updateCallbackId, callback);
|
||||||
|
startNavigationalUpdates(updateCallbackId);
|
||||||
|
return updateCallbackId;
|
||||||
|
} else {
|
||||||
|
callbacks.remove(params.getCallbackId());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NavUpdateListener navUpdateListener = null;
|
||||||
|
|
||||||
|
public boolean isActiveListeners() {
|
||||||
|
return callbacks.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startNavigationalUpdates(final long updateCallbackId) {
|
||||||
|
final ADirectionInfo directionInfo = new ADirectionInfo(-1, -1, false);
|
||||||
|
final NextDirectionInfo baseNdi = new NextDirectionInfo();
|
||||||
|
navUpdateListener = new NavUpdateListener() {
|
||||||
|
@Override
|
||||||
|
public void onNavUpdate() {
|
||||||
|
RoutingHelper rh = app.getRoutingHelper();
|
||||||
|
if (callbacks.containsKey(updateCallbackId)) {
|
||||||
|
if (rh.isDeviatedFromRoute()) {
|
||||||
|
directionInfo.setTurnType(TurnType.OFFR);
|
||||||
|
directionInfo.setDistanceTo((int) rh.getRouteDeviation());
|
||||||
|
} else {
|
||||||
|
NextDirectionInfo ndi = rh.getNextRouteDirectionInfo(baseNdi, true);
|
||||||
|
if (ndi != null && ndi.distanceTo > 0 && ndi.directionInfo != null) {
|
||||||
|
directionInfo.setDistanceTo(ndi.distanceTo);
|
||||||
|
directionInfo.setTurnType(ndi.directionInfo.getTurnType().getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
callbacks.get(updateCallbackId).updateNavigationInfo(directionInfo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.debug(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface NavUpdateListener {
|
||||||
|
void onNavUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean getBitmapForGpx(final Uri gpxUri, final float density, final int widthPixels, final int heightPixels, final int color, final GpxBitmapCreatedCallback callback) {
|
boolean getBitmapForGpx(final Uri gpxUri, final float density, final int widthPixels, final int heightPixels, final int color, final GpxBitmapCreatedCallback callback) {
|
||||||
if (gpxUri == null || callback == null) {
|
if (gpxUri == null || callback == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2103,6 +2167,8 @@ public class OsmandAidlApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static AGpxFileDetails createGpxFileDetails(@NonNull GPXTrackAnalysis a) {
|
private static AGpxFileDetails createGpxFileDetails(@NonNull GPXTrackAnalysis a) {
|
||||||
return new AGpxFileDetails(a.totalDistance, a.totalTracks, a.startTime, a.endTime,
|
return new AGpxFileDetails(a.totalDistance, a.totalTracks, a.startTime, a.endTime,
|
||||||
a.timeSpan, a.timeMoving, a.totalDistanceMoving, a.diffElevationUp, a.diffElevationDown,
|
a.timeSpan, a.timeMoving, a.totalDistanceMoving, a.diffElevationUp, a.diffElevationDown,
|
||||||
|
@ -2181,4 +2247,10 @@ public class OsmandAidlApi {
|
||||||
public interface OsmandAppInitCallback {
|
public interface OsmandAppInitCallback {
|
||||||
void onAppInitialized();
|
void onAppInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface DirectionsUpdateCallback {
|
||||||
|
void onDirectionsUpdate(ADirectionInfo directionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,4 +18,19 @@ public interface OsmandAidlConstants {
|
||||||
int COPY_FILE_WRITE_LOCK_ERROR = -1003;
|
int COPY_FILE_WRITE_LOCK_ERROR = -1003;
|
||||||
int COPY_FILE_IO_ERROR = -1004;
|
int COPY_FILE_IO_ERROR = -1004;
|
||||||
int COPY_FILE_UNSUPPORTED_FILE_TYPE_ERROR = -1005;
|
int COPY_FILE_UNSUPPORTED_FILE_TYPE_ERROR = -1005;
|
||||||
|
|
||||||
|
int TURN_TYPE_C = 1;//"C"; // continue (go straight) //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_TL = 2; // turn left //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_TSLL = 3; // turn slightly left //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_TSHL = 4; // turn sharply left //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_TR = 5; // turn right //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_TSLR = 6; // turn slightly right //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_TSHR = 7; // turn sharply right //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_KL = 8; // keep left //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_KR = 9; // keep right//$NON-NLS-1$
|
||||||
|
int TURN_TYPE_TU = 10; // U-turn //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_TRU = 11; // Right U-turn //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_OFFR = 12; // Off route //$NON-NLS-1$
|
||||||
|
int TURN_TYPE_RNDB = 13; // Roundabout
|
||||||
|
int TURN_TYPE_RNLB = 14; // Roundabout left
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.os.RemoteException;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.aidl.OsmandAidlApi.DirectionsUpdateCallback;
|
||||||
import net.osmand.aidl.OsmandAidlApi.GpxBitmapCreatedCallback;
|
import net.osmand.aidl.OsmandAidlApi.GpxBitmapCreatedCallback;
|
||||||
import net.osmand.aidl.OsmandAidlApi.OsmandAppInitCallback;
|
import net.osmand.aidl.OsmandAidlApi.OsmandAppInitCallback;
|
||||||
import net.osmand.aidl.OsmandAidlApi.SearchCompleteCallback;
|
import net.osmand.aidl.OsmandAidlApi.SearchCompleteCallback;
|
||||||
|
@ -50,6 +51,8 @@ import net.osmand.aidl.mapwidget.UpdateMapWidgetParams;
|
||||||
import net.osmand.aidl.navdrawer.NavDrawerFooterParams;
|
import net.osmand.aidl.navdrawer.NavDrawerFooterParams;
|
||||||
import net.osmand.aidl.navdrawer.NavDrawerHeaderParams;
|
import net.osmand.aidl.navdrawer.NavDrawerHeaderParams;
|
||||||
import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams;
|
import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams;
|
||||||
|
import net.osmand.aidl.navigation.ADirectionInfo;
|
||||||
|
import net.osmand.aidl.navigation.ANavigationUpdateParams;
|
||||||
import net.osmand.aidl.navigation.MuteNavigationParams;
|
import net.osmand.aidl.navigation.MuteNavigationParams;
|
||||||
import net.osmand.aidl.navigation.NavigateGpxParams;
|
import net.osmand.aidl.navigation.NavigateGpxParams;
|
||||||
import net.osmand.aidl.navigation.NavigateParams;
|
import net.osmand.aidl.navigation.NavigateParams;
|
||||||
|
@ -68,6 +71,8 @@ import net.osmand.aidl.search.SearchResult;
|
||||||
import net.osmand.aidl.tiles.ASqliteDbFile;
|
import net.osmand.aidl.tiles.ASqliteDbFile;
|
||||||
import net.osmand.aidl.copyfile.CopyFileParams;
|
import net.osmand.aidl.copyfile.CopyFileParams;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||||
|
import net.osmand.plus.routing.RouteDirectionInfo;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -992,5 +997,20 @@ public class OsmandAidlService extends Service {
|
||||||
return UNKNOWN_API_ERROR;
|
return UNKNOWN_API_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long registerForNavigationUpdates(ANavigationUpdateParams params, final IOsmAndAidlCallback callback) {
|
||||||
|
try {
|
||||||
|
OsmandAidlApi api = getApi("registerForNavUpdates");
|
||||||
|
if (api != null) {
|
||||||
|
return api.registerForNavigationUpdates(params, callback);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
handleException(e);
|
||||||
|
return UNKNOWN_API_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
package net.osmand.aidl.navigation;
|
||||||
|
|
||||||
|
parcelable ADirectionInfo;
|
73
OsmAnd/src/net/osmand/aidl/navigation/ADirectionInfo.java
Normal file
73
OsmAnd/src/net/osmand/aidl/navigation/ADirectionInfo.java
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package net.osmand.aidl.navigation;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
public class ADirectionInfo implements Parcelable {
|
||||||
|
|
||||||
|
private int distanceTo; //distance to next turn
|
||||||
|
private int turnType; //turn type
|
||||||
|
private boolean isLeftSide; //is movement leftsided
|
||||||
|
|
||||||
|
public ADirectionInfo(int distanceTo, int turnType, boolean isLeftSide) {
|
||||||
|
this.distanceTo = distanceTo;
|
||||||
|
this.turnType = turnType;
|
||||||
|
this.isLeftSide = isLeftSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ADirectionInfo(Parcel in) {
|
||||||
|
distanceTo = in.readInt();
|
||||||
|
turnType = in.readInt();
|
||||||
|
isLeftSide = in.readByte() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<ADirectionInfo> CREATOR = new Creator<ADirectionInfo>() {
|
||||||
|
@Override
|
||||||
|
public ADirectionInfo createFromParcel(Parcel in) {
|
||||||
|
return new ADirectionInfo(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ADirectionInfo[] newArray(int size) {
|
||||||
|
return new ADirectionInfo[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public int getDistanceTo() {
|
||||||
|
return distanceTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTurnType() {
|
||||||
|
return turnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLeftSide() {
|
||||||
|
return isLeftSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDistanceTo(int distanceTo) {
|
||||||
|
this.distanceTo = distanceTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTurnType(int turnType) {
|
||||||
|
this.turnType = turnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLeftSide(boolean leftSide) {
|
||||||
|
isLeftSide = leftSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(distanceTo);
|
||||||
|
dest.writeInt(turnType);
|
||||||
|
dest.writeByte((byte) (isLeftSide ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
package net.osmand.aidl.navigation;
|
||||||
|
|
||||||
|
parcelable ANavigationUpdateParams;
|
|
@ -0,0 +1,57 @@
|
||||||
|
package net.osmand.aidl.navigation;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
public class ANavigationUpdateParams implements Parcelable {
|
||||||
|
|
||||||
|
private boolean subscribeToUpdates = true;
|
||||||
|
private long callbackId = -1L;
|
||||||
|
|
||||||
|
public ANavigationUpdateParams() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCallbackId() {
|
||||||
|
return callbackId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallbackId(long callbackId) {
|
||||||
|
this.callbackId = callbackId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubscribeToUpdates(boolean subscribeToUpdates) {
|
||||||
|
this.subscribeToUpdates = subscribeToUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubscribeToUpdates() {
|
||||||
|
return subscribeToUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ANavigationUpdateParams(Parcel in) {
|
||||||
|
callbackId = in.readLong();
|
||||||
|
subscribeToUpdates = in.readByte() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeLong(callbackId);
|
||||||
|
dest.writeByte((byte) (subscribeToUpdates ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<ANavigationUpdateParams> CREATOR = new Creator<ANavigationUpdateParams>() {
|
||||||
|
@Override
|
||||||
|
public ANavigationUpdateParams createFromParcel(Parcel in) {
|
||||||
|
return new ANavigationUpdateParams(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ANavigationUpdateParams[] newArray(int size) {
|
||||||
|
return new ANavigationUpdateParams[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -502,6 +502,9 @@ public class RoutingHelper {
|
||||||
route.updateCurrentRoute(newCurrentRoute + 1);
|
route.updateCurrentRoute(newCurrentRoute + 1);
|
||||||
currentRoute = newCurrentRoute + 1;
|
currentRoute = newCurrentRoute + 1;
|
||||||
app.getNotificationHelper().refreshNotification(NotificationType.NAVIGATION);
|
app.getNotificationHelper().refreshNotification(NotificationType.NAVIGATION);
|
||||||
|
if (app.getAidlApi().isActiveListeners() && app.getAidlApi().navUpdateListener != null) {
|
||||||
|
app.getAidlApi().navUpdateListener.onNavUpdate();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue