ui opt:分体机部分按钮背景图替换
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package com.mogo.och.bus;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.mogo.och.IMogoOCH;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
class MogoOCHNoop implements IMogoOCH {
|
||||
|
||||
private static final String TAG = "MogoOCHNoop";
|
||||
|
||||
@Override
|
||||
public void init( FragmentActivity activity, int containerId ) {
|
||||
Logger.d( TAG, "noop-" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
Logger.d( TAG, "noop-" );
|
||||
}
|
||||
}
|
||||
@@ -39,15 +39,18 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
|
||||
if (Boolean.valueOf(RELEASE)) {
|
||||
implementation rootProject.ext.dependencies.mogooch
|
||||
implementation rootProject.ext.dependencies.mogoutils
|
||||
implementation rootProject.ext.dependencies.mogocommons
|
||||
implementation rootProject.ext.dependencies.mogomodulecommon
|
||||
} else {
|
||||
implementation project(":OCH:mogo-och")
|
||||
implementation project(":foudations:mogo-utils")
|
||||
implementation project(":foudations:mogo-commons")
|
||||
implementation project(":modules:mogo-module-common")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.mogo.och.taxi;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.mogo.och.IMogoOCH;
|
||||
import com.mogo.och.OCHConstants;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
* <p>
|
||||
* 网约车-出租车
|
||||
*/
|
||||
@Route( path = OCHConstants.PATH )
|
||||
class MogoOCHTaxi implements IMogoOCH {
|
||||
|
||||
private static final String TAG = "MogoOCHTaxi";
|
||||
|
||||
@Override
|
||||
public void init( FragmentActivity activity, int containerId ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
Logger.d( TAG, "init" );
|
||||
MogoOCHTaxiModel.getInstance().init( context );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package com.mogo.och.taxi;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.mogo.commons.data.BaseData;
|
||||
import com.mogo.commons.network.SubscribeImpl;
|
||||
import com.mogo.module.common.MogoApisHandler;
|
||||
import com.mogo.module.common.constants.HostConst;
|
||||
import com.mogo.service.adas.IMogoAdasOCHCallback;
|
||||
import com.mogo.service.adas.RemoteControlAutoPilotParameters;
|
||||
import com.mogo.service.adas.entity.AdasOCHData;
|
||||
import com.mogo.service.connection.IMogoOnMessageListener;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
import com.mogo.utils.network.RequestOptions;
|
||||
import com.mogo.utils.network.utils.GsonUtil;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class MogoOCHTaxiModel {
|
||||
|
||||
private static final String TAG = "MogoOCHTaxiModel";
|
||||
|
||||
private static volatile MogoOCHTaxiModel sInstance;
|
||||
private Context mContext;
|
||||
private OCHTaxiResponse mCurrentOCHOrder;
|
||||
private OCHArriveNotifyCallback mNotifyCallback;
|
||||
|
||||
private MogoOCHTaxiModel() {
|
||||
}
|
||||
|
||||
public static MogoOCHTaxiModel getInstance() {
|
||||
if ( sInstance == null ) {
|
||||
synchronized ( MogoOCHTaxiModel.class ) {
|
||||
if ( sInstance == null ) {
|
||||
sInstance = new MogoOCHTaxiModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private OrderMsgListener mOrderMsgListener;
|
||||
private OrderStatusMsgListener mOrderStatusMsgListener;
|
||||
private OCHTaxiServiceApi mOCHTaxiServiceApi;
|
||||
|
||||
private Object readResolve() {
|
||||
// 阻止反序列化,必须实现 Serializable 接口
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void init( Context context ) {
|
||||
mContext = context.getApplicationContext();
|
||||
|
||||
MogoApisHandler.getInstance()
|
||||
.getApis()
|
||||
.getSocketManagerApi( context )
|
||||
.registerOnMessageListener( 401016, mOrderMsgListener = new OrderMsgListener() );
|
||||
MogoApisHandler.getInstance()
|
||||
.getApis()
|
||||
.getSocketManagerApi( context )
|
||||
.registerOnMessageListener( 401019, mOrderStatusMsgListener = new OrderStatusMsgListener() );
|
||||
MogoApisHandler.getInstance()
|
||||
.getApis()
|
||||
.getAdasControllerApi()
|
||||
.addAdasOCHCallback( mNotifyCallback = new OCHArriveNotifyCallback() );
|
||||
|
||||
}
|
||||
|
||||
private class OrderMsgListener implements IMogoOnMessageListener< OCHTaxiResponse > {
|
||||
@Override
|
||||
public Class< OCHTaxiResponse > target() {
|
||||
return OCHTaxiResponse.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMsgReceived( OCHTaxiResponse obj ) {
|
||||
mCurrentOCHOrder = obj;
|
||||
}
|
||||
}
|
||||
|
||||
private class OrderStatusMsgListener implements IMogoOnMessageListener< OCHTaxiOrderStatusResponse > {
|
||||
|
||||
@Override
|
||||
public Class target() {
|
||||
return OCHTaxiOrderStatusResponse.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMsgReceived( OCHTaxiOrderStatusResponse obj ) {
|
||||
if ( obj == null ) {
|
||||
return;
|
||||
}
|
||||
OCHOrderStatus status = OCHOrderStatus.valueOf( obj.orderDispatchType );
|
||||
switch ( status ) {
|
||||
case Cancel:
|
||||
clearCurrentOCHOrder();
|
||||
break;
|
||||
default:
|
||||
Logger.d( TAG, "current order status: %s", status );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class OCHArriveNotifyCallback implements IMogoAdasOCHCallback {
|
||||
@Override
|
||||
public void onArriveAt( AdasOCHData data ) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param orderStatus 订单状态
|
||||
*/
|
||||
public void updateOCHOrderStatus( OCHOrderStatus orderStatus, OCHOrderStatusCallback callback ) {
|
||||
if ( mCurrentOCHOrder == null ) {
|
||||
return;
|
||||
}
|
||||
if ( mOCHTaxiServiceApi == null ) {
|
||||
mOCHTaxiServiceApi = MogoApisHandler.getInstance().getApis().getNetworkApi().create( OCHTaxiServiceApi.class, HostConst.OCH_DOMAIN );
|
||||
}
|
||||
mOCHTaxiServiceApi.updateOrderStatus( new OCHTaxiOrderStatus( mCurrentOCHOrder.orderNo, orderStatus.getCode() ) )
|
||||
.subscribeOn( Schedulers.io() )
|
||||
.observeOn( AndroidSchedulers.mainThread() )
|
||||
.subscribe( new SubscribeImpl< BaseData >( RequestOptions.create( mContext ) ) {
|
||||
@Override
|
||||
public void onSuccess( BaseData o ) {
|
||||
super.onSuccess( o );
|
||||
if ( callback != null ) {
|
||||
callback.onSuccess();
|
||||
}
|
||||
if ( orderStatus == OCHOrderStatus.Completed ) {
|
||||
clearCurrentOCHOrder();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError( Throwable e ) {
|
||||
super.onError( e );
|
||||
if ( callback != null ) {
|
||||
callback.onFail();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError( String message, int code ) {
|
||||
super.onError( message, code );
|
||||
if ( callback != null ) {
|
||||
callback.onFail();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public void clearCurrentOCHOrder() {
|
||||
mCurrentOCHOrder = null;
|
||||
}
|
||||
|
||||
private boolean checkCurrentOCHOrder() {
|
||||
if ( mCurrentOCHOrder != null
|
||||
&& mCurrentOCHOrder.drivingRoute != null
|
||||
&& mCurrentOCHOrder.drivingRoute.size() >= 2 ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void startAutoPilot() {
|
||||
if ( !checkCurrentOCHOrder() ) {
|
||||
Logger.e( TAG, "no order or order is empty." );
|
||||
return;
|
||||
}
|
||||
RemoteControlAutoPilotParameters parameters = new RemoteControlAutoPilotParameters();
|
||||
parameters.vehicleType = mCurrentOCHOrder.orderType;
|
||||
parameters.startLatLon = new RemoteControlAutoPilotParameters.AutoPilotLonLat( mCurrentOCHOrder.drivingRoute.get( 0 ).lat, mCurrentOCHOrder.drivingRoute.get( 0 ).lon );
|
||||
parameters.endLatLon = new RemoteControlAutoPilotParameters.AutoPilotLonLat( mCurrentOCHOrder.drivingRoute.get( 1 ).lat, mCurrentOCHOrder.drivingRoute.get( 1 ).lon );
|
||||
MogoApisHandler.getInstance()
|
||||
.getApis()
|
||||
.getAdasControllerApi()
|
||||
.aiCloudToAdasData( parameters );
|
||||
Logger.d( TAG, "start autopilot with parameter: %s", GsonUtil.jsonFromObject( parameters ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.mogo.och.taxi;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
*
|
||||
* 未派单 0
|
||||
* 去往上车站点 1
|
||||
* 已到达上车站点 2
|
||||
* 去往下车站点 3
|
||||
* 到达下车站点 4
|
||||
* 已完成 5
|
||||
* 已取消 6
|
||||
*/
|
||||
enum OCHOrderStatus {
|
||||
|
||||
None( 0 ),
|
||||
OnTheWayToStartStation( 1 ),
|
||||
ArriveAtStartStation( 2 ),
|
||||
OnTheWayToEndStation( 3 ),
|
||||
ArriveAtEndStation( 4 ),
|
||||
Completed( 5 ),
|
||||
Cancel( 6 );
|
||||
|
||||
private int code;
|
||||
|
||||
OCHOrderStatus( int code ) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public static OCHOrderStatus valueOf( int code ) {
|
||||
for ( OCHOrderStatus value : OCHOrderStatus.values() ) {
|
||||
if ( value.code == code ) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.och.taxi;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
*
|
||||
* 修改订单状态回调接口
|
||||
*/
|
||||
interface OCHOrderStatusCallback {
|
||||
|
||||
void onSuccess();
|
||||
|
||||
void onFail();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.mogo.och.taxi;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
*
|
||||
* 修改网约车-出租车订单状态的数据结构
|
||||
*/
|
||||
class OCHTaxiOrderStatus {
|
||||
|
||||
public String orderNo;
|
||||
public int orderDispatchType;
|
||||
|
||||
public OCHTaxiOrderStatus( String orderNo, int orderDispatchType ) {
|
||||
this.orderNo = orderNo;
|
||||
this.orderDispatchType = orderDispatchType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.mogo.och.taxi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class OCHTaxiOrderStatusResponse {
|
||||
|
||||
// 订单号
|
||||
public String orderNo;
|
||||
|
||||
// 订单运营类型 (9出租车,10小巴)
|
||||
public int orderType;
|
||||
|
||||
// 起始站名称
|
||||
public String startStation;
|
||||
public String startStationId;
|
||||
|
||||
// 目的站名称
|
||||
public String endStation;
|
||||
public String endStationId;
|
||||
|
||||
// 当前订单状态
|
||||
/**
|
||||
* 未派单 0
|
||||
* 去往上车站点 1
|
||||
* 已到达上车站点 2
|
||||
* 去往下车站点 3
|
||||
* 到达下车站点 4
|
||||
* 已完成 5
|
||||
* 已取消 6
|
||||
*/
|
||||
public int orderDispatchType;
|
||||
|
||||
// 起始站目的站距离km
|
||||
public double travelDistance;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.mogo.och.taxi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class OCHTaxiResponse {
|
||||
|
||||
// 订单号
|
||||
public String orderNo;
|
||||
// 订单运营类型 (9出租车,10小巴)
|
||||
public int orderType;
|
||||
// 起始站名称
|
||||
public String startStation;
|
||||
// 目的站名称
|
||||
public String endStation;
|
||||
// 当前订单状态
|
||||
public int orderDispatchType;
|
||||
// 起始站目的站距离km
|
||||
public double travelDistance;
|
||||
// 站点
|
||||
public List< OCHTaxiStation > drivingRoute;
|
||||
|
||||
public static class OCHTaxiStation {
|
||||
public int siteId;
|
||||
public String siteName;
|
||||
public double lon;
|
||||
public double lat;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.mogo.och.taxi;
|
||||
|
||||
import com.mogo.commons.data.BaseData;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.POST;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
*
|
||||
* 网约车-出租车接口
|
||||
*/
|
||||
interface OCHTaxiServiceApi {
|
||||
|
||||
@Headers( {"Content-type:application/json;charset=UTF-8"} )
|
||||
@POST( "/yycp-onlinecar-hailing/onlineCarHailing/order/updateOCHOrder/v1" )
|
||||
Observable< BaseData > updateOrderStatus( @Body OCHTaxiOrderStatus status );
|
||||
}
|
||||
@@ -157,7 +157,7 @@ ext {
|
||||
gpssimulatordebug : "com.mogo.module:module-gps-simulator-debug:${MOGO_MODULE_GPS_SIMULATOR_DEBUG_VERSION}",
|
||||
gpssimulatornoop : "com.mogo.module:module-gps-simulator-noop:${MOGO_MODULE_GPS_SIMULATOR_NOOP_VERSION}",
|
||||
|
||||
adasapi : "com.zhidao.autopilot.support:adas:1.0.6.5",
|
||||
adasapi : "com.zhidao.autopilot.support:adas:1.0.6.6",
|
||||
adasconfigapi : "com.zhidao.adasconfig:adasconfig:1.1.5.2",
|
||||
|
||||
// 个人中心的SDK
|
||||
|
||||
@@ -22,5 +22,7 @@ public class HostConst {
|
||||
public static final String IM_SOCKET_DOMAIN = "dzt-im.zhidaozhixing.com";
|
||||
public static final String WEBSOCKET_DOMAIN = "dzt-Instant.zhidaozhixing.com";
|
||||
|
||||
// 网约车
|
||||
public static final String OCH_DOMAIN = "http://dzt-hailing.zhidaozhixing.com";
|
||||
|
||||
}
|
||||
|
||||
@@ -128,4 +128,8 @@ public interface IMogoADASController extends IProvider {
|
||||
* @param callback
|
||||
*/
|
||||
void removeAdasRecognizedDataCallback( IMogoAdasRecognizedDataCallback callback );
|
||||
|
||||
void addAdasOCHCallback( IMogoAdasOCHCallback callback );
|
||||
|
||||
void removeAdasOCHCallback();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.service.adas;
|
||||
|
||||
import com.mogo.service.adas.entity.AdasOCHData;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/18
|
||||
*
|
||||
* 自动驾驶到站回调
|
||||
*/
|
||||
interface IMogoAdasOCHCallback {
|
||||
|
||||
void onArriveAt( AdasOCHData data );
|
||||
}
|
||||
@@ -15,9 +15,18 @@ class RemoteControlAutoPilotParameters {
|
||||
public List< AutoPilotLonLat > wayLatLons;
|
||||
public AutoPilotLonLat endLatLon;
|
||||
public float speedLimit;
|
||||
public int vehicleType;// 运营类型
|
||||
|
||||
public static class AutoPilotLonLat {
|
||||
public double lat;
|
||||
public double lon;
|
||||
|
||||
public AutoPilotLonLat() {
|
||||
}
|
||||
|
||||
public AutoPilotLonLat( double lat, double lon ) {
|
||||
this.lat = lat;
|
||||
this.lon = lon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.mogo.service.adas.entity;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/18
|
||||
*
|
||||
* 自动驾驶网约车回调数据
|
||||
*/
|
||||
class AdasOCHData {
|
||||
|
||||
public int type;
|
||||
public double lon;
|
||||
public double lat;
|
||||
|
||||
public AdasOCHData( int type, double lon, double lat ) {
|
||||
this.type = type;
|
||||
this.lon = lon;
|
||||
this.lat = lat;
|
||||
}
|
||||
}
|
||||
@@ -21,12 +21,14 @@ import com.mogo.module.common.utils.CarSeries;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.adas.IMogoADASController;
|
||||
import com.mogo.service.adas.IMogoAdasDataCallback;
|
||||
import com.mogo.service.adas.IMogoAdasOCHCallback;
|
||||
import com.mogo.service.adas.IMogoAdasRecognizedDataCallback;
|
||||
import com.mogo.service.adas.IMogoAdasWarnMessageCallback;
|
||||
import com.mogo.service.adas.RemoteControlAutoPilotParameters;
|
||||
import com.mogo.service.adas.entity.ADASRecognizedListResult;
|
||||
import com.mogo.service.adas.entity.ADASRecognizedResult;
|
||||
import com.mogo.service.adas.entity.ADASWarnMessage;
|
||||
import com.mogo.service.adas.entity.AdasOCHData;
|
||||
import com.mogo.service.impl.singleton.SingletonsHolder;
|
||||
import com.mogo.service.statusmanager.IMogoStatusManager;
|
||||
import com.mogo.utils.TipToast;
|
||||
@@ -42,6 +44,7 @@ import com.zhidao.adasconfig.common.config.EnumSkinStyle;
|
||||
import com.zhidao.autopilot.support.api.AutopilotServiceManage;
|
||||
import com.zhidao.autopilot.support.api.IAutopilotServiceStatusListener;
|
||||
import com.zhidao.autopilot.support.api.IAutopolitDataCallBack;
|
||||
import com.zhidao.autopilotservice.model.AdasAIDLAutopilotArriveModel;
|
||||
import com.zhidao.support.adas.high.OnAdasListener;
|
||||
import com.zhidao.support.adas.high.bean.RectInfo;
|
||||
import com.zhidao.support.adas.high.bean.WarnMessageInfo;
|
||||
@@ -156,6 +159,7 @@ public class MogoADASController implements IMogoADASController {
|
||||
* 缓存容器
|
||||
*/
|
||||
List< RectInfo > mCacheRecognizedDataSet = new ArrayList<>();
|
||||
private IMogoAdasOCHCallback mAdasOCHCallback;
|
||||
|
||||
/**
|
||||
* 处理数据,将识别到的物体分组,然后每1s进行一次回调
|
||||
@@ -306,6 +310,20 @@ public class MogoADASController implements IMogoADASController {
|
||||
public void showToast( String msg ) {
|
||||
UiThreadHandler.post( () -> TipToast.tip( msg ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autopilotArrive( AdasAIDLAutopilotArriveModel autopilotArriveModel ) {
|
||||
if ( autopilotArriveModel == null ) {
|
||||
return;
|
||||
}
|
||||
if ( mAdasOCHCallback != null ) {
|
||||
mAdasOCHCallback.onArriveAt( new AdasOCHData(
|
||||
autopilotArriveModel.getCarType(),
|
||||
autopilotArriveModel.getLon(),
|
||||
autopilotArriveModel.getLat() )
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
AutopilotServiceManage.getInstance().registerAutopilotDataListener( mAutopolitDataCallBack );
|
||||
}
|
||||
@@ -585,4 +603,15 @@ public class MogoADASController implements IMogoADASController {
|
||||
}
|
||||
mMogoAdasRecognizedDataCallbacks.remove( callback );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addAdasOCHCallback( IMogoAdasOCHCallback callback ) {
|
||||
mAdasOCHCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAdasOCHCallback() {
|
||||
mAdasOCHCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user