[fea]
[增加结束虚拟单按钮]
This commit is contained in:
yangyakun
2024-11-20 15:47:39 +08:00
parent 94046a67fd
commit 6a062c6dc6
25 changed files with 116 additions and 2677 deletions

View File

@@ -1,29 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.och.common.module">
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!--查找蓝牙设备-->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<!--使当前设备可被其他蓝牙设备检测到-->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<!--与已配对的蓝牙设备进行通讯-->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!--使用蓝牙扫描结果来推导物理位置-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application>
<activity
android:name=".wigets.media.MediaPlayerActivity"

View File

@@ -51,37 +51,5 @@ open class BaseBluetoothManager {
ToastUtils.showShort("设备无蓝牙硬件")
return BluetoothState.NONE
}
fun requestPermission(){
if (PermissionUtil.checkPermission(AbsMogoApplication.getApp(), *permissionlist)) {
}else{
//申请悬浮窗权限
val shouldShowRequestPermissionRationale = ActivityUtils.getTopActivity()
.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
if(shouldShowRequestPermissionRationale){// 可以弹窗系统权限框
ActivityCompat.requestPermissions(
ActivityUtils.getTopActivity(),
permissionlist, MainPresenter.MOGO_PERMISSION_REQUEST_CODE
)
}else{// 不会弹系统弹窗
PermissionsDialogUtils.openAppDetails(ActivityUtils.getTopActivity(), "蓝牙", 100)
}
}
}
fun checkPermission():Boolean{
AbsMogoApplication.getApp()?.let {
permissionlist.forEach { permission->
val checkSelfPermission = ActivityCompat.checkSelfPermission(it, permission)
if (PackageManager.PERMISSION_GRANTED!=checkSelfPermission) {
return false
}
}
}
return true
}
}

View File

@@ -13,6 +13,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:src="@drawable/common_dialog_close"
android:visibility="gone"
android:layout_marginEnd="@dimen/dp_50"
android:layout_marginTop="@dimen/dp_50"
android:layout_width="@dimen/dp_60"

View File

@@ -33,4 +33,10 @@
<string name="common_biz_loading">加载中……</string>
<string name="common_empty_data">暂无数据</string>
<string name="common_error_data">重新加载</string>
<string name="common_dialog_title">提示</string>
<string name="common_dialog_confirm">确认</string>
<string name="common_dialog_cancel">取消</string>
</resources>

View File

@@ -4,4 +4,23 @@
package="com.mogo.och.shuttle.weaknet.passenger">
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!--查找蓝牙设备-->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<!--使当前设备可被其他蓝牙设备检测到-->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<!--与已配对的蓝牙设备进行通讯-->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!--使用蓝牙扫描结果来推导物理位置-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>

View File

@@ -3,6 +3,7 @@ package com.mogo.och.unmanned.taxi.network
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.data.BaseData
import com.mogo.och.common.module.manager.cache.OchSPManager
import com.mogo.och.data.taxi.QueryCarOrderByNoReqBean
import com.mogo.och.data.taxi.QueryCarOrderByNoRespBean
import com.mogo.och.unmanned.taxi.bean.ArriveSiteReqBean
@@ -150,4 +151,12 @@ interface TaxiTaskWithOrderServiceApi {
@Body data: QueryCarOrderByNoReqBean?
): Observable<QueryCarOrderByNoRespBean>
@Headers("Content-type:application/json;charset=UTF-8")
@GET("/och-taxi-cabin/api/flow/v1/resetInit")
fun resetInit(
@Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId,
@Header("ticket") ticket: String = SharedPrefsMgr.getInstance().token,
@Query("sn") sn: String? = OchSPManager.getSn()
): Observable<QueryCarOrderByNoRespBean>
}

View File

@@ -157,6 +157,18 @@ object TaxiTaskWithOrderServiceManager {
.subscribe(OchCommonSubscribeImpl(context, callback, "orderCompleted"))
}
/**
* 服务完成
*/
@JvmStatic
fun resetInit(
context: Context, callback: OchCommonServiceCallback<BaseData>?
) {
mOCHTaxiServiceApi.resetInit().transformTry()
.subscribe(OchCommonSubscribeImpl(context, callback, "orderCompleted"))
}
/**
* 取消订单
*/

View File

@@ -1,5 +1,7 @@
package com.mogo.och.unmanned.taxi.ui.base;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
@@ -80,6 +82,11 @@ public class TaxiPresenter extends Presenter<TaxiFragment> implements ITaxiADASS
}
private final OchTransformDispatch ochTransform = new OchTransformDispatch(){
@Override
public void setVideoView(@Nullable View target) {
}
@Override
public void logout() {
TaxiTaskModel.INSTANCE.logout();

View File

@@ -1,641 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.routing;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.view.View;
import android.view.ViewPropertyAnimator;
import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
/**
* This implementation of {@link RecyclerView.ItemAnimator} provides basic
* animations on remove, add, and move events that happen to the items in
* a RecyclerView. RecyclerView uses a DefaultItemAnimator by default.
*
* @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator)
*/
public class TaxiRoutingChooseLineItemOpenAnimator extends DefaultItemAnimator {
private static final boolean DEBUG = false;
private static TimeInterpolator sDefaultInterpolator;
private final ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>();
private final ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
private final ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
private final ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();
private final ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>();
private final ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
private final ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();
private final ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList<>();
private final ArrayList<RecyclerView.ViewHolder> mMoveAnimations = new ArrayList<>();
private final ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>();
private final ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList<>();
private static class MoveInfo {
public RecyclerView.ViewHolder holder;
public int fromX, fromY, toX, toY;
MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
this.holder = holder;
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
}
}
private static class ChangeInfo {
public RecyclerView.ViewHolder oldHolder, newHolder;
public int fromX, fromY, toX, toY;
private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
this.oldHolder = oldHolder;
this.newHolder = newHolder;
}
ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) {
this(oldHolder, newHolder);
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
}
@Override
public String toString() {
return "ChangeInfo{"
+ "oldHolder=" + oldHolder
+ ", newHolder=" + newHolder
+ ", fromX=" + fromX
+ ", fromY=" + fromY
+ ", toX=" + toX
+ ", toY=" + toY
+ '}';
}
}
@Override
public void runPendingAnimations() {
boolean removalsPending = !mPendingRemovals.isEmpty();
boolean movesPending = !mPendingMoves.isEmpty();
boolean changesPending = !mPendingChanges.isEmpty();
boolean additionsPending = !mPendingAdditions.isEmpty();
if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
// nothing to animate
return;
}
// First, remove stuff
for (RecyclerView.ViewHolder holder : mPendingRemovals) {
animateRemoveImpl(holder);
}
mPendingRemovals.clear();
// Next, move stuff
if (movesPending) {
final ArrayList<MoveInfo> moves = new ArrayList<>(mPendingMoves);
mMovesList.add(moves);
mPendingMoves.clear();
Runnable mover = () -> {
for (MoveInfo moveInfo : moves) {
animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
moveInfo.toX, moveInfo.toY);
}
moves.clear();
mMovesList.remove(moves);
};
if (removalsPending) {
View view = moves.get(0).holder.itemView;
ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
} else {
mover.run();
}
}
// Next, change stuff, to run in parallel with move animations
if (changesPending) {
final ArrayList<ChangeInfo> changes = new ArrayList<>(mPendingChanges);
mChangesList.add(changes);
mPendingChanges.clear();
Runnable changer = () -> {
for (ChangeInfo change : changes) {
animateChangeImpl(change);
}
changes.clear();
mChangesList.remove(changes);
};
if (removalsPending) {
RecyclerView.ViewHolder holder = changes.get(0).oldHolder;
ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
} else {
changer.run();
}
}
// Next, add stuff
if (additionsPending) {
final ArrayList<RecyclerView.ViewHolder> additions = new ArrayList<>(mPendingAdditions);
mAdditionsList.add(additions);
mPendingAdditions.clear();
Runnable adder = () -> {
for (RecyclerView.ViewHolder holder : additions) {
animateAddImpl(holder);
}
additions.clear();
mAdditionsList.remove(additions);
};
if (removalsPending || movesPending || changesPending) {
long removeDuration = removalsPending ? getRemoveDuration() : 0;
long moveDuration = movesPending ? getMoveDuration() : 0;
long changeDuration = changesPending ? getChangeDuration() : 0;
long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
View view = additions.get(0).itemView;
ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
} else {
adder.run();
}
}
}
@Override
public boolean animateRemove(final RecyclerView.ViewHolder holder) {
resetAnimation(holder);
mPendingRemovals.add(holder);
return true;
}
private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView;
final ViewPropertyAnimator animation = view.animate();
mRemoveAnimations.add(holder);
animation.setDuration(getRemoveDuration()).alpha(0).setListener(
new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchRemoveStarting(holder);
}
@Override
public void onAnimationEnd(Animator animator) {
animation.setListener(null);
view.setAlpha(1);
dispatchRemoveFinished(holder);
mRemoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}
@Override
public boolean animateAdd(final RecyclerView.ViewHolder holder) {
resetAnimation(holder);
holder.itemView.setAlpha(0);
mPendingAdditions.add(holder);
return true;
}
void animateAddImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView;
final ViewPropertyAnimator animation = view.animate();
mAddAnimations.add(holder);
animation.alpha(1).setDuration(getAddDuration())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchAddStarting(holder);
}
@Override
public void onAnimationCancel(Animator animator) {
view.setAlpha(1);
}
@Override
public void onAnimationEnd(Animator animator) {
animation.setListener(null);
dispatchAddFinished(holder);
mAddAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}
@Override
public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY,
int toX, int toY) {
final View view = holder.itemView;
fromX += (int) holder.itemView.getTranslationX();
fromY += (int) holder.itemView.getTranslationY();
resetAnimation(holder);
int deltaX = toX - fromX;
int deltaY = toY - fromY;
if (deltaX == 0 && deltaY == 0) {
dispatchMoveFinished(holder);
return false;
}
if (deltaX != 0) {
view.setTranslationX(-deltaX);
}
if (deltaY != 0) {
view.setTranslationY(-deltaY);
}
mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
return true;
}
void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
final View view = holder.itemView;
final int deltaX = toX - fromX;
final int deltaY = toY - fromY;
if (deltaX != 0) {
view.animate().translationX(0);
}
if (deltaY != 0) {
view.animate().translationY(0);
}
// TODO: make EndActions end listeners instead, since end actions aren't called when
// vpas are canceled (and can't end them. why?)
// need listener functionality in VPACompat for this. Ick.
final ViewPropertyAnimator animation = view.animate();
mMoveAnimations.add(holder);
animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchMoveStarting(holder);
}
@Override
public void onAnimationCancel(Animator animator) {
if (deltaX != 0) {
view.setTranslationX(0);
}
if (deltaY != 0) {
view.setTranslationY(0);
}
}
@Override
public void onAnimationEnd(Animator animator) {
animation.setListener(null);
dispatchMoveFinished(holder);
mMoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}
@Override
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) {
if (oldHolder == newHolder) {
// Don't know how to run change animations when the same view holder is re-used.
// run a move animation to handle position changes.
return animateMove(oldHolder, fromX, fromY, toX, toY);
}
final float prevTranslationX = oldHolder.itemView.getTranslationX();
final float prevTranslationY = oldHolder.itemView.getTranslationY();
final float prevAlpha = oldHolder.itemView.getAlpha();
resetAnimation(oldHolder);
int deltaX = (int) (toX - fromX - prevTranslationX);
int deltaY = (int) (toY - fromY - prevTranslationY);
// recover prev translation state after ending animation
oldHolder.itemView.setTranslationX(prevTranslationX);
oldHolder.itemView.setTranslationY(prevTranslationY);
oldHolder.itemView.setAlpha(prevAlpha);
if (newHolder != null) {
// carry over translation values
resetAnimation(newHolder);
newHolder.itemView.setTranslationX(-deltaX);
newHolder.itemView.setTranslationY(-deltaY);
newHolder.itemView.setAlpha(0);
}
mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
return true;
}
void animateChangeImpl(final ChangeInfo changeInfo) {
final RecyclerView.ViewHolder holder = changeInfo.oldHolder;
final View view = holder == null ? null : holder.itemView;
final RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
final View newView = newHolder != null ? newHolder.itemView : null;
if (view != null) {
final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(
getChangeDuration());
mChangeAnimations.add(changeInfo.oldHolder);
oldViewAnim.translationX((float) (changeInfo.toX - changeInfo.fromX));
oldViewAnim.translationY((float) (changeInfo.toY - changeInfo.fromY));
oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchChangeStarting(changeInfo.oldHolder, true);
}
@Override
public void onAnimationEnd(Animator animator) {
oldViewAnim.setListener(null);
view.setAlpha(1);
view.setTranslationX(0);
view.setTranslationY(0);
dispatchChangeFinished(changeInfo.oldHolder, true);
mChangeAnimations.remove(changeInfo.oldHolder);
dispatchFinishedWhenDone();
}
}).start();
}
if (newView != null) {
final ViewPropertyAnimator newViewAnimation = newView.animate();
mChangeAnimations.add(changeInfo.newHolder);
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration())
.alpha(1).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchChangeStarting(changeInfo.newHolder, false);
}
@Override
public void onAnimationEnd(Animator animator) {
newViewAnimation.setListener(null);
newView.setAlpha(1);
newView.setTranslationX(0);
newView.setTranslationY(0);
dispatchChangeFinished(changeInfo.newHolder, false);
mChangeAnimations.remove(changeInfo.newHolder);
dispatchFinishedWhenDone();
}
}).start();
}
}
private void endChangeAnimation(List<ChangeInfo> infoList, RecyclerView.ViewHolder item) {
for (int i = infoList.size() - 1; i >= 0; i--) {
ChangeInfo changeInfo = infoList.get(i);
if (endChangeAnimationIfNecessary(changeInfo, item)) {
if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
infoList.remove(changeInfo);
}
}
}
}
private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
if (changeInfo.oldHolder != null) {
endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
}
if (changeInfo.newHolder != null) {
endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
}
}
private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) {
boolean oldItem = false;
if (changeInfo.newHolder == item) {
changeInfo.newHolder = null;
} else if (changeInfo.oldHolder == item) {
changeInfo.oldHolder = null;
oldItem = true;
} else {
return false;
}
item.itemView.setAlpha(1);
item.itemView.setTranslationX(0);
item.itemView.setTranslationY(0);
dispatchChangeFinished(item, oldItem);
return true;
}
@Override
public void endAnimation(RecyclerView.ViewHolder item) {
final View view = item.itemView;
// this will trigger end callback which should set properties to their target values.
view.animate().cancel();
// TODO if some other animations are chained to end, how do we cancel them as well?
for (int i = mPendingMoves.size() - 1; i >= 0; i--) {
MoveInfo moveInfo = mPendingMoves.get(i);
if (moveInfo.holder == item) {
view.setTranslationY(0);
view.setTranslationX(0);
dispatchMoveFinished(item);
mPendingMoves.remove(i);
}
}
endChangeAnimation(mPendingChanges, item);
if (mPendingRemovals.remove(item)) {
view.setAlpha(1);
dispatchRemoveFinished(item);
}
if (mPendingAdditions.remove(item)) {
view.setAlpha(1);
dispatchAddFinished(item);
}
for (int i = mChangesList.size() - 1; i >= 0; i--) {
ArrayList<ChangeInfo> changes = mChangesList.get(i);
endChangeAnimation(changes, item);
if (changes.isEmpty()) {
mChangesList.remove(i);
}
}
for (int i = mMovesList.size() - 1; i >= 0; i--) {
ArrayList<MoveInfo> moves = mMovesList.get(i);
for (int j = moves.size() - 1; j >= 0; j--) {
MoveInfo moveInfo = moves.get(j);
if (moveInfo.holder == item) {
view.setTranslationY(0);
view.setTranslationX(0);
dispatchMoveFinished(item);
moves.remove(j);
if (moves.isEmpty()) {
mMovesList.remove(i);
}
break;
}
}
}
for (int i = mAdditionsList.size() - 1; i >= 0; i--) {
ArrayList<RecyclerView.ViewHolder> additions = mAdditionsList.get(i);
if (additions.remove(item)) {
view.setAlpha(1);
dispatchAddFinished(item);
if (additions.isEmpty()) {
mAdditionsList.remove(i);
}
}
}
// animations should be ended by the cancel above.
//noinspection Pointless BooleanExpression,ConstantConditions
if (mRemoveAnimations.remove(item) && DEBUG) {
throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mRemoveAnimations list");
}
//noinspection Pointless BooleanExpression,ConstantConditions
if (mAddAnimations.remove(item) && DEBUG) {
throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mAddAnimations list");
}
//noinspection Pointless BooleanExpression,ConstantConditions
if (mChangeAnimations.remove(item) && DEBUG) {
throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mChangeAnimations list");
}
//noinspection Pointless BooleanExpression,ConstantConditions
if (mMoveAnimations.remove(item) && DEBUG) {
throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mMoveAnimations list");
}
dispatchFinishedWhenDone();
}
private void resetAnimation(RecyclerView.ViewHolder holder) {
if (sDefaultInterpolator == null) {
sDefaultInterpolator = new ValueAnimator().getInterpolator();
}
holder.itemView.animate().setInterpolator(sDefaultInterpolator);
endAnimation(holder);
}
@Override
public boolean isRunning() {
return (!mPendingAdditions.isEmpty()
|| !mPendingChanges.isEmpty()
|| !mPendingMoves.isEmpty()
|| !mPendingRemovals.isEmpty()
|| !mMoveAnimations.isEmpty()
|| !mRemoveAnimations.isEmpty()
|| !mAddAnimations.isEmpty()
|| !mChangeAnimations.isEmpty()
|| !mMovesList.isEmpty()
|| !mAdditionsList.isEmpty()
|| !mChangesList.isEmpty());
}
/**
* Check the state of currently pending and running animations. If there are none
* pending/running, call {@link #dispatchAnimationsFinished()} to notify any
* listeners.
*/
void dispatchFinishedWhenDone() {
if (!isRunning()) {
dispatchAnimationsFinished();
}
}
@Override
public void endAnimations() {
int count = mPendingMoves.size();
for (int i = count - 1; i >= 0; i--) {
MoveInfo item = mPendingMoves.get(i);
View view = item.holder.itemView;
view.setTranslationY(0);
view.setTranslationX(0);
dispatchMoveFinished(item.holder);
mPendingMoves.remove(i);
}
count = mPendingRemovals.size();
for (int i = count - 1; i >= 0; i--) {
RecyclerView.ViewHolder item = mPendingRemovals.get(i);
dispatchRemoveFinished(item);
mPendingRemovals.remove(i);
}
count = mPendingAdditions.size();
for (int i = count - 1; i >= 0; i--) {
RecyclerView.ViewHolder item = mPendingAdditions.get(i);
item.itemView.setAlpha(1);
dispatchAddFinished(item);
mPendingAdditions.remove(i);
}
count = mPendingChanges.size();
for (int i = count - 1; i >= 0; i--) {
endChangeAnimationIfNecessary(mPendingChanges.get(i));
}
mPendingChanges.clear();
if (!isRunning()) {
return;
}
int listCount = mMovesList.size();
for (int i = listCount - 1; i >= 0; i--) {
ArrayList<MoveInfo> moves = mMovesList.get(i);
count = moves.size();
for (int j = count - 1; j >= 0; j--) {
MoveInfo moveInfo = moves.get(j);
RecyclerView.ViewHolder item = moveInfo.holder;
View view = item.itemView;
view.setTranslationY(0);
view.setTranslationX(0);
dispatchMoveFinished(moveInfo.holder);
moves.remove(j);
if (moves.isEmpty()) {
mMovesList.remove(moves);
}
}
}
listCount = mAdditionsList.size();
for (int i = listCount - 1; i >= 0; i--) {
ArrayList<RecyclerView.ViewHolder> additions = mAdditionsList.get(i);
count = additions.size();
for (int j = count - 1; j >= 0; j--) {
RecyclerView.ViewHolder item = additions.get(j);
View view = item.itemView;
view.setAlpha(1);
dispatchAddFinished(item);
additions.remove(j);
if (additions.isEmpty()) {
mAdditionsList.remove(additions);
}
}
}
listCount = mChangesList.size();
for (int i = listCount - 1; i >= 0; i--) {
ArrayList<ChangeInfo> changes = mChangesList.get(i);
count = changes.size();
for (int j = count - 1; j >= 0; j--) {
endChangeAnimationIfNecessary(changes.get(j));
if (changes.isEmpty()) {
mChangesList.remove(changes);
}
}
}
cancelAll(mRemoveAnimations);
cancelAll(mMoveAnimations);
cancelAll(mAddAnimations);
cancelAll(mChangeAnimations);
dispatchAnimationsFinished();
}
void cancelAll(List<RecyclerView.ViewHolder> viewHolders) {
for (int i = viewHolders.size() - 1; i >= 0; i--) {
viewHolders.get(i).itemView.animate().cancel();
}
}
/**
* {@inheritDoc}
* <p>
* If the payload list is not empty, DefaultItemAnimator returns <code>true</code>.
* When this is the case:
* <ul>
* <li>If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both
* ViewHolder arguments will be the same instance.
* </li>
* <li>
* If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)},
* then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and
* run a move animation instead.
* </li>
* </ul>
*/
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull List<Object> payloads) {
return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
}
}

View File

@@ -1,98 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.routing
import android.content.Context
import android.widget.ImageView
import android.widget.TextView
import androidx.lifecycle.LifecycleObserver
import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog
import com.mogo.och.unmanned.taxi.R
class TaxiRoutingFeedbackDialog : BaseFloatDialog, LifecycleObserver {
private var commonConfirm: TextView? = null
private var commonCancel: TextView? = null
private var commonTips: TextView? = null
private var commonCloseIcon: ImageView? = null
private var clickListener: TaxiRoutingFeedBackDialogClickListener? = null
constructor(builder: Builder, context: Context) : super(context) {
commonTips?.text = builder.tipsStr
commonCancel?.text = builder.cancelStr
commonConfirm?.text = builder.confirmStr
clickListener = builder.clickListener
}
init {
setContentView(R.layout.unmanned_dialog_routing_feedback_result)
setCanceledOnTouchOutside(true)
commonConfirm = findViewById(R.id.routing_common_confirm)
commonCancel = findViewById(R.id.routing_common_cancel)
commonTips = findViewById(R.id.routing_common_tips)
commonCloseIcon = findViewById(R.id.closeDialogIcon)
commonCloseIcon?.setOnClickListener {
dismiss()
}
commonConfirm?.setOnClickListener {
clickListener?.confirm()
dismiss()
}
commonCancel?.setOnClickListener {
clickListener?.cancel()
dismiss()
}
}
fun showDialog() {
if (isShowing) {
return
}
show()
}
fun hideDialog() {
if (isShowing) {
dismiss()
}
}
interface TaxiRoutingFeedBackDialogClickListener {
fun confirm()
fun cancel()
}
class Builder {
var tipsStr: String = ""
var confirmStr: String = ""
var cancelStr: String = ""
var clickListener: TaxiRoutingFeedBackDialogClickListener? = null
fun tips(tips: String): Builder {
this.tipsStr = tips
return this
}
fun confirmStr(commit: String): Builder {
this.confirmStr = commit
return this
}
fun cancelStr(cancel: String): Builder {
this.cancelStr = cancel
return this
}
fun clickListener(listener: TaxiRoutingFeedBackDialogClickListener): Builder {
this.clickListener = listener
return this
}
fun build(context: Context): TaxiRoutingFeedbackDialog? {
return TaxiRoutingFeedbackDialog(this, context)
}
}
}

View File

@@ -1,73 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.routing
import android.animation.ObjectAnimator
import android.content.Context
import android.view.animation.LinearInterpolator
import androidx.lifecycle.LifecycleObserver
import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.unmanned.taxi.R
import kotlinx.android.synthetic.main.unmanned_dialog_routing_loading.dialog_loading_text
import kotlinx.android.synthetic.main.unmanned_dialog_routing_loading.dialog_loading_view
/**
* loading
*/
class TaxiRoutingLoadingDialog : BaseFloatDialog, LifecycleObserver {
private var objectAnimator: ObjectAnimator? = null
private val mLoadingView by lazy { dialog_loading_view }
private val mLoadingText by lazy { dialog_loading_text }
private var mRunnable:Runnable= Runnable {
ToastUtils.showLong("超时未响应,请求失败")
hideLoading()
}
constructor(context: Context) : super(context)
init {
setContentView(R.layout.unmanned_dialog_routing_loading)
setCanceledOnTouchOutside(false)
}
/**
* 开始旋转
*/
private fun startRotation() {
objectAnimator = ObjectAnimator.ofFloat(mLoadingView, "rotation", -720f, 0f)
objectAnimator?.let {
it.duration = 3000
it.repeatCount = -1
it.interpolator = LinearInterpolator()
it.start()
}
}
/**
* 停止旋转
*/
private fun stopRotation() {
objectAnimator?.let {
if (it.isRunning) {
it.end()
objectAnimator = null
}
}
}
/**
* 显示dialog
*/
fun showLoading() {
mLoadingText.text = "请求中,请稍后..."
startRotation()
show()
}
/**
* 隐藏dialog
*/
fun hideLoading() {
stopRotation()
dismiss()
}
}

View File

@@ -13,8 +13,6 @@ object TaxiRoutingModel {
mOrderStatusCallback = callback
}
/**
* 显示/隐藏 前往任务目的地的导航
*

View File

@@ -1,34 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.routing
import com.mogo.och.unmanned.taxi.base.IUiIntent
import com.mogo.och.unmanned.taxi.bean.EndGrayTaskFeedbackType
import com.mogo.och.unmanned.taxi.bean.GrayLineBean
sealed class TaxiRoutingUiIntent : IUiIntent {
//打开选择路线页面
data class StartChooseLineAction(val currentTimestamp: Long) : TaxiRoutingUiIntent()
//查询灰度线路列表
data class QueryRoutingGrayLineList(val currentTimestamp: Long) : TaxiRoutingUiIntent()
//开始一个任务并查询此任务对应的轨迹详情
data class StartTaskAndQueryContrail(val grayLineBean: GrayLineBean) : TaxiRoutingUiIntent()
//展示Routing任务信息
data class ShowRoutingTask(val routingTask: RoutingUIState.RoutingTask) :
TaxiRoutingUiIntent()
//开始任务
data class StartTaskAction(val routingTask: RoutingUIState.RoutingTask) : TaxiRoutingUiIntent()
//问题打点
data class SubmitGrayLineIssueLocation(val grayId: Long) : TaxiRoutingUiIntent()
//展示结束任务反馈弹框
data class ShowFeedbackDialog(val grayId: Long) : TaxiRoutingUiIntent()
//结束任务
data class SubmitEndTask(val grayId: Long, val type: EndGrayTaskFeedbackType,val occurrenceTime:Long) :
TaxiRoutingUiIntent()
}

View File

@@ -1,36 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.routing
import com.mogo.och.unmanned.taxi.base.IUiState
import com.mogo.och.unmanned.taxi.bean.ContrailBean
import com.mogo.och.unmanned.taxi.bean.GrayLineBean
data class TaxiRoutingUiState(val routingUiState: RoutingUIState) : IUiState
/**
* 算路UI状态
*/
sealed class RoutingUIState {
object Init : RoutingUIState()
data class ShowGrayLineList(var data: MutableList<GrayLineBean>) : RoutingUIState()
data class HideChooseLineLoading(var isCosePage: Boolean) : RoutingUIState()
data class PostRoutingTaskResult(
val grayLineBean: GrayLineBean?,
val contrailBean: ContrailBean?,
val grayId: Long?
) : RoutingUIState()
data class RoutingTask(
val grayLineBean: GrayLineBean?,
val contrailBean: ContrailBean?,
val grayId: Long?
) : RoutingUIState()
data class ShowFinishTaskButton(val routingTask: RoutingTask) : RoutingUIState()
data class ShowFeedbackDialog(val grayId: Long, val currentTimestamp: Long) : RoutingUIState()
object DismissFeedbackDialog : RoutingUIState()
}

View File

@@ -19,7 +19,6 @@ import com.mogo.och.common.module.wigets.dialog.CommonDialogView
import com.mogo.och.common.module.wigets.dialog.CommonFeedbackDialog
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.bean.PointError
import com.mogo.och.unmanned.taxi.ui.routing.TaxiRoutingLoadingDialog
import kotlinx.android.synthetic.main.taxt_report_error_point_panel.view.lvs_loding
import kotlinx.android.synthetic.main.taxt_report_error_point_panel.view.rvErrorPointReason
import kotlinx.android.synthetic.main.taxt_report_error_point_panel.view.tv_report_error_point_reason

View File

@@ -22,7 +22,6 @@ import com.mogo.och.unmanned.taxi.bean.EndGrayTaskFeedbackType
import com.mogo.och.unmanned.taxi.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.unmanned.taxi.constant.TaxiUnmannedConst
import com.mogo.och.unmanned.taxi.ui.routing.RoutingSwitchModel
import com.mogo.och.unmanned.taxi.ui.routing.TaxiRoutingFeedbackDialog
import com.mogo.och.unmanned.taxi.ui.routing.TaxiRoutingModel
import com.mogo.och.common.module.map.MapMakerManager
import com.mogo.och.common.module.wigets.dialog.CommonDialogStatus
@@ -59,9 +58,6 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
private var swtichViewModel: RoutingSwitchModel?=null
private var mFeedbackDialog: TaxiRoutingFeedbackDialog? = null
init {
LayoutInflater.from(context).inflate(R.layout.unmanned_routing_running, this, true)
initView()
@@ -85,10 +81,6 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
}
private fun hideFeedbackDialog() {
mFeedbackDialog?.hideDialog()
}
private fun showFeedbackDialog(grayId: Long) {
val occurrenceTime = System.currentTimeMillis()
CommonDialogStatus
@@ -116,35 +108,6 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
}
})
.build(context).show()
// val builder: TaxiRoutingFeedbackDialog.Builder = TaxiRoutingFeedbackDialog.Builder()
// builder.cancelStr(
// MainMoGoApplication.getApp()
// .getString(R.string.routing_feedback_result_btn_not_sure)
// ).confirmStr(
// MainMoGoApplication.getApp()
// .getString(R.string.routing_feedback_result_btn_sure)
// ).tips(MainMoGoApplication.getApp().getString(R.string.routing_feedback_result_hint))
// .clickListener(object :
// TaxiRoutingFeedbackDialog.TaxiRoutingFeedBackDialogClickListener {
// override fun confirm() {
// swtichViewModel?.showLoading()
// viewModel?.endGrayTask( grayId,
// EndGrayTaskFeedbackType.USABLE_YES,
// occurrenceTime)
// }
//
// override fun cancel() {
// swtichViewModel?.showLoading()
// viewModel?.endGrayTask( grayId,
// EndGrayTaskFeedbackType.USABLE_NO,
// occurrenceTime)
// }
// })
// mFeedbackDialog = builder.build(context)
// mFeedbackDialog?.showDialog()
}
/**
@@ -294,7 +257,6 @@ class RoutingRunningView: ConstraintLayout, RoutingRunningModel.RoutingRuningCal
override fun onSubmitEndTaskFailed(errorStr: String) {
ToastUtils.showShort(errorStr)
hideFeedbackDialog()
viewModel?.data?.let {
swtichViewModel?.showRoutingRunning(it)
}

View File

@@ -15,7 +15,6 @@ import com.mogo.och.unmanned.taxi.bean.GrayLineBean
import com.mogo.och.unmanned.taxi.bean.StartGrayAndQueryContrailRsp
import com.mogo.och.unmanned.taxi.ui.debug.DebugView
import com.mogo.och.unmanned.taxi.ui.routing.RoutingSwitchModel
import com.mogo.och.unmanned.taxi.ui.routing.TaxiRoutingChooseLineItemOpenAnimator
import com.mogo.och.unmanned.taxi.ui.routing.routingselect.RoutingSelectModel.SwtichRoutingViewCallback
import kotlinx.android.synthetic.main.unmanned_routing_select.view.include_empty
import kotlinx.android.synthetic.main.unmanned_routing_select.view.include_error
@@ -58,7 +57,6 @@ class RoutingSelectView: ConstraintLayout, SwtichRoutingViewCallback {
mLinearLayoutManager = WrapContentLinearLayoutManager(context)
switch_routing_rv.layoutManager = mLinearLayoutManager
switch_routing_rv.itemAnimator = TaxiRoutingChooseLineItemOpenAnimator()
mChooseLineListAdapter = RoutingItemAdapter(context, mRoutingLineList)
switch_routing_rv.addItemDecoration(SpacesItemDecoration(AutoSizeUtils.dp2px(context,20f)))
switch_routing_rv.adapter = mChooseLineListAdapter

View File

@@ -1,862 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.task
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.os.CountDownTimer
import android.text.TextUtils
import android.view.View
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.amap.api.navi.model.NaviLatLng
import com.mogo.commons.mvp.BaseFragment
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.getState
import com.mogo.eagle.core.function.hmi.ui.widget.ItinerarySummaryDialog
import com.mogo.eagle.core.function.main.MainMoGoApplication
import com.mogo.eagle.core.network.utils.GsonUtil
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.i
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_TAXI
import com.mogo.eagle.core.utilcode.util.ClickUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.biz.order.TaxiOrderStatusEnum
import com.mogo.och.common.module.manager.autopilot.location.OchLocationManager
import com.mogo.och.common.module.map.AmapNaviToDestinationModel
import com.mogo.och.common.module.map.ICommonNaviChangedCallback
import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.common.module.utils.FlowBus
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.common.module.wigets.OCHCommitDialog
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.bean.OrderDetail
import com.mogo.och.unmanned.taxi.bean.QueryCurrentTaskRespBean
import com.mogo.och.unmanned.taxi.bean.StartServiceRespBean
import com.mogo.och.unmanned.taxi.constant.TaskStatusEnum
import com.mogo.och.unmanned.taxi.constant.TaskTypeEnum
import com.mogo.och.unmanned.taxi.constant.TaxiDriverEventConst
import com.mogo.och.unmanned.taxi.constant.TaxiUnmannedConst.Companion.TAXI_END_MAP_MAKER
import com.mogo.och.unmanned.taxi.constant.TaxiUnmannedConst.Companion.TAXI_START_MAP_MAKER
import com.mogo.och.unmanned.taxi.constant.TaxiUnmannedConst.Companion.TYPE_MARKER_TAXI_ORDER
import com.mogo.och.common.module.map.MapMakerManager
import com.mogo.och.unmanned.taxi.utils.TaskUtils
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.cancelOrder
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.endPoint
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.endStationName
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.mCurrentTaskLayout
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.naviToEnd
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.naviToStart
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.noTaskData
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.orderPhoneAndNum
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.pathwayPoint
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.startPoint
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.startStationName
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.taskClickBtn
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.taskOtherInfo
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.taskStatus
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.taskTypeTv
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.trajectoryType
import kotlinx.android.synthetic.main.unmanned_taxi_no_data_common_view.noOrderDataTv
import kotlinx.android.synthetic.main.unmanned_taxi_no_data_common_view.prepareTaskCountdownTv
import kotlinx.coroutines.flow.map
/**
* @author: wangmingjun
* @date: 2023/7/24
*/
class TaxiCurrentTaskFragment : BaseFragment(),
View.OnClickListener, ICommonNaviChangedCallback {
private lateinit var mViewModel: TaxiCurrentTaskViewModel
private var mPrepareTasCountDownTimer: CountDownTimer? = null
private var dialog:ItinerarySummaryDialog? = null
companion object {
const val TAG = M_TAXI + "TaxiCurrentTaskFragment"
fun newInstance(): TaxiCurrentTaskFragment {
val args = Bundle()
val fragment = TaxiCurrentTaskFragment()
fragment.arguments = args
return fragment
}
}
override fun getLayoutId(): Int {
return R.layout.unmanned_task_fragment_current
}
override fun getTagName(): String {
return this.javaClass.simpleName
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mViewModel = ViewModelProvider(
this,
ViewModelProvider.NewInstanceFactory()
)[TaxiCurrentTaskViewModel::class.java]
}
override fun initViews() {
initOnClickListener()
initContainerView(false)
initTaskDebugViewListener()
initViewModelObserver()
}
/**
* 是否有正在进行的订单进行UI显示
*
* @param hasCurrentTask
*/
private fun initContainerView(hasCurrentTask: Boolean) {
d(
TAG,
"hasCurrentTask = $hasCurrentTask"
)
if (hasCurrentTask) {
noTaskData.visibility = View.GONE
mCurrentTaskLayout.visibility = View.VISIBLE
} else {
noTaskData.visibility = View.VISIBLE
noOrderDataTv.text = "暂无进行中订单"
mCurrentTaskLayout.visibility = View.GONE
taskOtherInfo.text = "距离 -- 公里, 用时 -- 分钟"
}
}
private fun initOnClickListener() {
naviToStart.setOnClickListener(this)
naviToEnd.setOnClickListener(this)
cancelOrder.setOnClickListener(this)
taskStatus.setOnClickListener(this)
taskClickBtn.setOnClickListener(this)
}
private fun initTaskDebugViewListener() {
taskStatus.setOnLongClickListener {
FlowBus.with<Boolean>(TaxiDriverEventConst.TaxiFragmentEvent.EVENT_TYPE_SHOW_DEBUG_VIEW)
.post(this.lifecycleScope, true)
false
}
}
private fun initViewModelObserver() {
mViewModel.sendUiIntent(TaskUiIntent.StartTaskWithOrderLooper)
//监听返回的数据状态
lifecycleScope.launchWhenStarted {
mViewModel.uiStateFlow.map { it.taskWithOrderUIState }.collect { taskAndOrderUiState ->
d(TAG, "uiStateFlow-initViewModelObserver: $taskAndOrderUiState")
when (taskAndOrderUiState) {
is TaskWithOrderUIState.Init -> {
}
// 开始接单后 需要将车开到最近的一个站点就位,然后才能开启 无人化 流程
is TaskWithOrderUIState.TaskDriveToNearestStationTask -> {
if (taskAndOrderUiState.driveToNearestStationTask != null) {
updateViewByDriveToNearestStationTask(taskAndOrderUiState.driveToNearestStationTask)
} else {
updatePrepareTaskDelayUI(0, false)
initContainerView(false)
removeAllMapMarker()
}
}
is TaskWithOrderUIState.TaskWithOrder -> {
val currentTaskWithOrder = taskAndOrderUiState.taskWithOrder
if (currentTaskWithOrder == null) {
initContainerView(false)
removeAllMapMarker()
} else {
updateViewByCurrentTaskWithOrder(currentTaskWithOrder)
}
updateNextTaskFragment(currentTaskWithOrder)
}
is TaskWithOrderUIState.UpdateOrderTripInfo -> {
dialog?.setOrderMileage(taskAndOrderUiState.mileage*1000)
taskOtherInfo.text =
TaskUtils.getCurrentTaskTotalAndDurationHtml(
taskAndOrderUiState.mileage,
taskAndOrderUiState.duration
)
}
is TaskWithOrderUIState.UpdateTaskTripLocalCalculateInfo -> {
updateCurrentTaskTripInfo(
taskAndOrderUiState.meters,
taskAndOrderUiState.timeInSecond
)
}
is TaskWithOrderUIState.UpdatePrepareTaskDelay -> {
updatePrepareTaskDelayUI(
taskAndOrderUiState.delayTime,
taskAndOrderUiState.isStart
)
}
}
}
}
}
/**
* 更新拉取任务倒计时
*/
private fun updatePrepareTaskDelayUI(millisInFuture: Long, isStart: Boolean) {
if (!isStart) {
prepareTaskCountdownTv.visibility = View.INVISIBLE
mPrepareTasCountDownTimer?.cancel()
mPrepareTasCountDownTimer = null
return
}
if (mPrepareTasCountDownTimer != null) {
mPrepareTasCountDownTimer?.cancel()
mPrepareTasCountDownTimer = null
}
prepareTaskCountdownTv.visibility = View.VISIBLE
mPrepareTasCountDownTimer =
object : CountDownTimer(millisInFuture, 1000L) {// 倒计时后开启自驾
override fun onTick(millisUntilFinished: Long) {
// 倒计时
UiThreadHandler.post {
prepareTaskCountdownTv.text =
"距离任务获取还有 ${DateTimeUtil.second2MMSS(millisUntilFinished / 1000)}"
}
}
override fun onFinish() {
//倒计时结束了...
UiThreadHandler.post {
prepareTaskCountdownTv.visibility = View.INVISIBLE
}
mPrepareTasCountDownTimer?.cancel()
}
}
mPrepareTasCountDownTimer?.start()
}
private fun updateViewByDriveToNearestStationTask(driveToNearestStationTask: StartServiceRespBean.Result?) {
if (driveToNearestStationTask == null) return
initContainerView(true)
// DriverToNearestStationTask 任务更新
taskStatus.visibility = View.VISIBLE
taskTypeTv.visibility = View.GONE
cancelOrder.visibility = View.GONE
orderPhoneAndNum.visibility = View.GONE
startStationName.visibility = View.VISIBLE
endStationName.visibility = View.VISIBLE
taskClickBtn.visibility = View.GONE
naviToStart.visibility = View.GONE
naviToEnd.visibility = View.VISIBLE
taskOtherInfo.visibility = View.VISIBLE
pathwayPoint.visibility = View.GONE
// 更新任务状态,起点,终点
taskStatus.text = resources.getString(R.string.task_start_to_virtual_site)
startStationName.text = resources.getString(R.string.task_current_loc)
endStationName.text = driveToNearestStationTask.siteName
updateStartAndEndStationPointByStatus(true)
setOrRemoveMapMaker(
true,
TAXI_END_MAP_MAKER,
driveToNearestStationTask.wgs84Lat,
driveToNearestStationTask.wgs84Lon,
R.raw.end_marker
)
// 使用高德获取导航数据
startNaviToStation(
false,
driveToNearestStationTask.gcjLat,
driveToNearestStationTask.gcjLon
)
}
private fun updateStartAndEndStationPointByStatus(isGoingToStation: Boolean) {
if (isGoingToStation) {// 即将到达的站点
startPoint.setImageResource(R.drawable.taxi_driver_circle_blue_big)
endPoint.setImageResource(R.drawable.taxi_driver_circle_green_big)
} else {// 到达站点 或 已经经过的站点
startPoint.setImageResource(R.drawable.taxi_driver_circle_green_big)
endPoint.setImageResource(R.drawable.taxi_driver_circle_blue_big)
}
}
private fun updateNextTaskFragment(result: QueryCurrentTaskRespBean.Result?) {
FlowBus.with<QueryCurrentTaskRespBean.Result?>(TaxiDriverEventConst.TabFragmentEvent.EVENT_TYPE_TASK_WITH_ORDER_CHANGED)
.post(this.lifecycleScope, result)
if (result != null
&& result.taskType == TaskTypeEnum.VirtualTask.code
&& result.order != null
&& result.currentStatus != TaskStatusEnum.CompleteTask.code
) {
VoiceNotice.showNotice("已为您提前接到下一订单,待完成当前任务后服务")
FlowBus.with<Boolean>(TaxiDriverEventConst.TabFragmentEvent.EVENT_TYPE_SHOW_RED_POINT)
.post(this.lifecycleScope, true)
} else {
FlowBus.with<Boolean>(TaxiDriverEventConst.TabFragmentEvent.EVENT_TYPE_SHOW_RED_POINT)
.post(this.lifecycleScope, false)
}
}
fun onCarTakeOrderStatusChanged() {
if (this::mViewModel.isInitialized) {
mViewModel.sendUiIntent(TaskUiIntent.StartOrEndTakeOrder)
} else {
CallerLogger.e(TAG, "onCarTakeOrderStatusChanged: mViewModel is not Initialized")
}
}
/**
* 根据任务状态计算剩余历程和时间
*/
private fun updateRemainDistanceAndTime(isVoicePlay: Boolean) {
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder() ?: return
d(TAG, "updateRemainDistanceAndTime ${currentTaskWithOrder.currentStatus}")
if (currentTaskWithOrder.currentStatus == TaskStatusEnum.StartTask.code) {
if (currentTaskWithOrder.endSite != null) {
startNaviToStation(
isVoicePlay, currentTaskWithOrder.endSite!!.gcjLat,
currentTaskWithOrder.endSite!!.gcjLon
)
}
} else if (currentTaskWithOrder.currentStatus == TaskStatusEnum.CompleteTask.code &&
currentTaskWithOrder.taskType <= TaskTypeEnum.ToOrderStartTask.code
) {
taskOtherInfo.text = "已到达 ${currentTaskWithOrder.endSite?.siteName}"
} else {
taskOtherInfo.text = "距离 -- 公里, 用时 -- 分钟"
}
}
/**
* 更新当前任务和订单信息
*/
private fun updateViewByCurrentTaskWithOrder(taskAndOrder: QueryCurrentTaskRespBean.Result?) {
if (taskAndOrder == null) return
/**
* 根据任务类型判断任务显示,
* 虚拟单, 显示在进行中 前往上车点
* 演练任务,显示演练任务, 同时有订单显示在待服务中
* 当前任务是接驾任务,显示订单状态+运营单 订单显示在进行中, 任务不再显示
*/
val taskType = taskAndOrder.taskType // 任务类型
val order = taskAndOrder.order // 订单信息
val endSite = taskAndOrder.endSite // 终点
val currentStatus = taskAndOrder.currentStatus // 任务的状态 0空闲 1:获取任务 2:开始任务 3:到达目的地
if ((endSite == null || currentStatus == TaskStatusEnum.CompleteTask.code) // 无任务或者任务已经完成的时候且无订单的时候
&& taskAndOrder.order == null
) {
initContainerView(false)
removeAllMapMarker()
return
}
initContainerView(true)
when (taskType) {
TaskTypeEnum.None.code -> {
if (order != null && (currentStatus == TaskStatusEnum.CompleteTask.code
|| currentStatus == TaskStatusEnum.None.code)
) { //暂停接单会清空前往上车点任务
updateOrderUI(order)
}
}
TaskTypeEnum.VirtualTask.code -> { //演练任务
if (order != null && currentStatus == TaskStatusEnum.CompleteTask.code) {
updateOrderUI(order)
} else {
updateVirtualTaskUI(taskAndOrder)
}
}
TaskTypeEnum.ToOrderEndTask.code, TaskTypeEnum.ToOrderStartTask.code -> {// 接驾任务 或 送驾任务
order?.also {
updatePathwayPoint(taskType, endSite?.siteName)
updateOrderUI(it)
}
}
}
updateMapMarkers(taskAndOrder)
updateRemainDistanceAndTime(false)
}
private fun updatePathwayPoint(taskType: Int, endSiteName: String?) {
if (TextUtils.isEmpty(endSiteName)) return
pathwayPoint.visibility = if (taskType == TaskTypeEnum.ToOrderStartTask.code)
View.VISIBLE else View.GONE
pathwayPoint.text = "途径: $endSiteName"
}
private fun updateMapMarkers(taskAndOrder: QueryCurrentTaskRespBean.Result?) {
if (taskAndOrder?.startSite != null
&& taskAndOrder.endSite != null
) {
when (taskAndOrder.currentStatus) {
TaskStatusEnum.GetTask.code -> {
setOrRemoveMapMaker(
true,
TAXI_START_MAP_MAKER,
taskAndOrder.startSite!!.wgs84Lat,
taskAndOrder.startSite!!.wgs84Lon,
R.raw.star_marker
)
setOrRemoveMapMaker(
true,
TAXI_END_MAP_MAKER,
taskAndOrder.endSite!!.wgs84Lat,
taskAndOrder.endSite!!.wgs84Lon,
R.raw.end_marker
)
}
TaskStatusEnum.StartTask.code -> {
setOrRemoveMapMaker(
false,
TAXI_START_MAP_MAKER,
taskAndOrder.startSite!!.wgs84Lat,
taskAndOrder.startSite!!.wgs84Lon,
R.raw.star_marker
)
setOrRemoveMapMaker(
true,
TAXI_END_MAP_MAKER,
taskAndOrder.endSite!!.wgs84Lat,
taskAndOrder.endSite!!.wgs84Lon,
R.raw.end_marker
)
}
TaskStatusEnum.CompleteTask.code -> {
setOrRemoveMapMaker(
false,
TAXI_START_MAP_MAKER,
taskAndOrder.startSite!!.wgs84Lat,
taskAndOrder.startSite!!.wgs84Lon,
R.raw.star_marker
)
setOrRemoveMapMaker(
false,
TAXI_END_MAP_MAKER,
taskAndOrder.endSite!!.wgs84Lat,
taskAndOrder.endSite!!.wgs84Lon,
R.raw.end_marker
)
}
}
} else {
d(
TAG,
"CurrentTaskWithOrder == " + GsonUtil.jsonFromObject(taskAndOrder)
)
}
}
private fun updateVirtualTaskUI(taskAndOrder: QueryCurrentTaskRespBean.Result?) {
if (taskAndOrder == null) return
val startSite = taskAndOrder.startSite // 起点
val endSite = taskAndOrder.endSite // 终点
val currentStatus = taskAndOrder.currentStatus // 任务的状态 0空闲 1:获取任务 2:开始任务 3:到达目的地
cancelOrder.visibility = View.GONE
orderPhoneAndNum.visibility = View.GONE
taskClickBtn.visibility = View.GONE
naviToStart.visibility = View.GONE
taskTypeTv.visibility = View.VISIBLE
naviToEnd.visibility =
if (currentStatus >= TaskStatusEnum.StartTask.code) View.VISIBLE else View.GONE
taskOtherInfo.visibility =
if (currentStatus == TaskStatusEnum.GetTask.code) View.GONE else View.VISIBLE
pathwayPoint.visibility = View.GONE
if (startSite == null || endSite == null) return
taskStatus.text = resources.getString(R.string.task_start_end_site)
taskTypeTv.background =
ContextCompat.getDrawable(
MainMoGoApplication.getApp().applicationContext, R.drawable.task_unreal_type_btn_bg
)
taskTypeTv.text = resources.getString(R.string.task_exercise)
startStationName.text = startSite.siteName
endStationName.text = endSite.siteName
TaxiTaskModel.getCurrentOrderTrajectoryList().also {
val taskTrajectory = it.firstOrNull {taskAndOrder.lineId == it.lineId}
trajectoryType.visibility = if (taskTrajectory?.source == 2)
View.VISIBLE else View.GONE
}
updatePrepareTaskDelayUI(0, false)
updateStartAndEndStationPointByStatus(true)
}
private fun updateOrderUI(order: OrderDetail) {
cancelOrder.visibility = if (order.orderStatus
== TaxiOrderStatusEnum.ArriveAtEnd.code
) View.GONE else View.VISIBLE
orderPhoneAndNum.visibility = View.VISIBLE
taskClickBtn.visibility = View.VISIBLE
taskTypeTv.visibility = View.VISIBLE
// orderStatus: 0 订单创建(为派单), 10 已派上司机(司机去往上车点), 20 司机到达上车点,
// 30 乘客到达上车点, 40 服务中(去往目的地), 50 到达目的地, 60 已完成, 70 已取消
naviToStart.visibility = if (order.orderStatus
== TaxiOrderStatusEnum.OnTheWayToStart.code
) View.VISIBLE else View.GONE
naviToEnd.visibility = if (order.orderStatus
== TaxiOrderStatusEnum.OnTheWayToEnd.code
) View.VISIBLE else View.GONE
taskOtherInfo.visibility = View.VISIBLE
updatePrepareTaskDelayUI(0, false)
taskTypeTv.text = resources.getString(R.string.task_order)
taskTypeTv.background =
ContextCompat.getDrawable(
MainMoGoApplication.getApp().applicationContext,
R.drawable.task_order_type_btn_bg
)
orderPhoneAndNum.text = TaskUtils.getCurrentTaskPhoneNumAndPassengerCountHtml(
order.bookingUserPhone,
order.passengerSize
)
startStationName.text = order.orderStartSite?.siteName
endStationName.text = order.orderEndSite?.siteName
TaxiTaskModel.getCurrentOrderTrajectoryList().also {
val orderTrajectory = it.firstOrNull {order.orderLine == it.lineId}
trajectoryType.visibility = if (orderTrajectory?.source == 2)
View.VISIBLE else View.GONE
}
when (order.orderStatus) {
TaxiOrderStatusEnum.None.code -> { //无
dismissDialog()
initContainerView(false)
removeAllMapMarker()
}
TaxiOrderStatusEnum.ArriveAtEnd.code -> { //到达目的地
taskStatus.text = resources.getString(R.string.task_start_end_site)
showDialog()
updateStartAndEndStationPointByStatus(true)
updateTaskContainerBottomBtn(
getString(R.string.module_och_taxi_order_server_end),
Color.parseColor("#FFFFFF"),
Color.parseColor("#FF1D5EF3"),
true
)
hideNaviBtns()
}
TaxiOrderStatusEnum.OnTheWayToEnd.code -> { //送驾中
dismissDialog()
taskStatus.text = resources.getString(R.string.task_start_end_site)
updateStartAndEndStationPointByStatus(true)
updateTaskContainerBottomBtn(
getString(R.string.module_och_taxi_order_close),
Color.parseColor("#FFFFFF"),
Color.parseColor("#FF1D5EF3"),
true
)
}
TaxiOrderStatusEnum.UserArriveAtStart.code, TaxiOrderStatusEnum.ArriveAtStart.code -> {
//乘客到达上车点, 验证成功 ; 到达乘客上车点
dismissDialog()
taskStatus.text = resources.getString(R.string.arrived_start_site)
updateStartAndEndStationPointByStatus(false)
updateTaskContainerBottomBtn(
if (order.orderStatus == TaxiOrderStatusEnum.UserArriveAtStart.code)
getString(R.string.module_och_taxi_order_server_start)
else getString(R.string.module_och_taxi_order_server_start_wait_check),
Color.parseColor("#FFFFFF"),
Color.parseColor("#FF1D5EF3"),
true
)
hideNaviBtns()
taskOtherInfo.text = TaskUtils.getCurrentTaskWaitTimeHtml()
}
TaxiOrderStatusEnum.OnTheWayToStart.code -> { //前往上车地点
dismissDialog()
taskStatus.text = resources.getString(R.string.task_start_start_site)
updateStartAndEndStationPointByStatus(false)
updateTaskContainerBottomBtn(
getString(R.string.module_och_taxi_order_server_start),
Color.parseColor("#4DFFFFFF"),
Color.parseColor("#4D1D5EF3"),
false
)
}
}
}
private fun hideNaviBtns() {
naviToStart.visibility = View.GONE
naviToEnd.visibility = View.GONE
AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi()
FlowBus.with<Boolean>(TaxiDriverEventConst.TaxiFragmentEvent.EVENT_TYPE_SHOW_AMAP_NAVI_TO_STATION_FRAGMENT)
.post(this.lifecycleScope, false)
FlowBus.with<Boolean>(TaxiDriverEventConst.TaxiFragmentEvent.EVENT_TYPE_SHOW_ROUTING_TO_STATION_FRAGMENT)
.post(this.lifecycleScope, false)
}
private fun startNaviToStation(isVoicePlay: Boolean, stationLat: Double, stationLng: Double) {
AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi()
val gcJ02Location = OchLocationManager.getGCJ02Location()
val mCurLatitude = gcJ02Location.latitude
val mCurLongitude = gcJ02Location.longitude
d(TAG, "currentLatLng=$mCurLatitude $mCurLongitude")
val startNaviLatLng = NaviLatLng(mCurLatitude, mCurLongitude)
val endNaviLatLng = NaviLatLng(stationLat, stationLng)
AmapNaviToDestinationModel.getInstance(context).initAMapNavi(startNaviLatLng, endNaviLatLng)
AmapNaviToDestinationModel.getInstance(context).setVoiceIsMute(isVoicePlay)
AmapNaviToDestinationModel.getInstance(context).setTaxiNaviChangedCallback(this)
}
/**
* 剩余里程和剩余时间
* @param meters 米
* @param timeInSecond 秒
*/
private fun updateCurrentTaskTripInfo(meters: Long, timeInSecond: Long) {
UiThreadHandler.post {
TaxiTaskModel.getCurrentTaskWithOrder() ?: return@post
d(
TAG,
"updateCurrentTaskTripInfo, taskUtil, ${
TaskUtils.getCurrentTaskTripHtml(
meters,
timeInSecond
)
}"
)
taskOtherInfo.text = TaskUtils.getCurrentTaskTripHtml(meters, timeInSecond)
}
}
override fun onDestroyView() {
AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi()
updatePrepareTaskDelayUI(0, false)
super.onDestroyView()
}
private fun startOrEndService() {
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
if (currentTaskWithOrder?.order == null) return
val order = currentTaskWithOrder.order
if (TaxiOrderStatusEnum.ArriveAtStart.code == order!!.orderStatus) { //到达乘客上车点,司机可跳过乘客屏认证
mViewModel.sendUiIntent(TaskUiIntent.JumpPassengerCheck)
} else if (TaxiOrderStatusEnum.UserArriveAtStart.code == order.orderStatus) {
mViewModel.sendUiIntent(TaskUiIntent.StartTask)
} else if (TaxiOrderStatusEnum.ArriveAtEnd.code == order.orderStatus) { //点击了完成服务,结束订单并更新订单信息
mViewModel.sendUiIntent(TaskUiIntent.JourneyCompleted)
} else if (TaxiOrderStatusEnum.OnTheWayToEnd.code == order.orderStatus) { //前往目的地过程中可提前结束行程
//自驾中提示,接管后才能结束
if (getState()
== IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
) {
ToastUtils.showLong(R.string.taxi_switch_line_btn_warning1)
} else {
closeOrderDialog()
}
}
}
private fun closeOrderDialog() {
val builder = OCHCommitDialog.Builder()
val closeOrderDialog = builder
.title(getString(R.string.dialog_order_close_title))
.tips(getString(R.string.dialog_order_close_content))
.confirmStr(getString(R.string.dialog_order_close_confirm))
.cancelStr(getString(R.string.dialog_order_close_cancel))
.build(requireContext())
closeOrderDialog!!.setClickListener(object : OCHCommitDialog.ClickListener {
override fun confirm() {
mViewModel.sendUiIntent(TaskUiIntent.CloseOrderByDriver)
}
override fun cancel() {
closeOrderDialog.dismiss()
}
})
closeOrderDialog.show()
}
override fun onClick(v: View) {
if (!ClickUtils.isFastClick()) {
i(TAG, "view点击过快")
return
}
when (v.id) {
taskClickBtn.id -> {
d(TAG, taskStatus.text.toString())
startOrEndService()
}
cancelOrder.id -> {
val currentWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
if (currentWithOrder?.order != null) {
val order = currentWithOrder.order
activity?.also {
}
}
}
naviToStart.id,
naviToEnd.id -> {
showNaviToEndStationFragment(true)
}
}
}
/**
* 显示/隐藏 前往任务目的地的导航
*
* @param isShow
*/
private fun showNaviToEndStationFragment(isShow: Boolean) {
FlowBus.with<Boolean>(TaxiDriverEventConst.TaxiFragmentEvent.EVENT_TYPE_START_NAVI_TO_END_STATION)
.post(this.lifecycleScope, isShow)
}
override fun onCurrentNaviDistAndTimeChanged(meters: Int, timeInSecond: Long) {
updateCurrentTaskTripInfo(meters.toLong(), timeInSecond)
}
override fun reInitNaviAmap(isPlay: Boolean, isRestart: Boolean) {
d(TAG, "isPlay = $isPlay, isRestart=$isRestart")
if (!isRestart) {
FlowBus.with<Boolean>(TaxiDriverEventConst.TaxiFragmentEvent.EVENT_TYPE_SHOW_AMAP_NAVI_TO_STATION_FRAGMENT)
.post(this.lifecycleScope, false)
return
}
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
UiThreadHandler.postDelayed({
updateRemainDistanceAndTime(false)
}, 2000)
UiThreadHandler.postDelayed({
if (currentTaskWithOrder?.currentStatus == TaskStatusEnum.GetTask.code
) {
if (naviToStart.visibility == View.GONE) {
naviToStart.visibility = View.VISIBLE
}
}
if ((currentTaskWithOrder?.currentStatus == TaskStatusEnum.StartTask.code
&& currentTaskWithOrder.order == null)
|| (currentTaskWithOrder?.order?.orderStatus == TaxiOrderStatusEnum.OnTheWayToEnd.code)
) {
if (naviToEnd.visibility == View.GONE) {
naviToEnd.visibility = View.VISIBLE
}
}
}, 3000)
}
fun onNaviToEndStationByAmap(isShow: Boolean) {
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder() ?: return
FlowBus.with<Boolean>(TaxiDriverEventConst.TaxiFragmentEvent.EVENT_TYPE_SHOW_AMAP_NAVI_TO_STATION_FRAGMENT)
.post(
this.lifecycleScope,
if (currentTaskWithOrder.currentStatus == TaskStatusEnum.StartTask.code)
isShow
else
true
)
updateRemainDistanceAndTime(
if (currentTaskWithOrder.currentStatus == TaskStatusEnum.StartTask.code)
isShow else true
)
}
/**
* 绘制地图起点终点
* @param isAdd
* @param uuid
*/
private fun setOrRemoveMapMaker(
isAdd: Boolean, uuid: String,
lat: Double, lon: Double, resourceId: Int
) {
if (isAdd) {
MapMakerManager.addMapMaker(TYPE_MARKER_TAXI_ORDER, uuid, lat, lon, resourceId)
} else {
MapMakerManager.removeMapMaker(uuid, lat, lon)
}
}
private fun removeAllMapMarker() {
MapMakerManager.removeAllMapMarkerByOwner(TYPE_MARKER_TAXI_ORDER)
}
private fun updateTaskContainerBottomBtn(
txt: String?,
txtColorId: Int,
bgColorId: Int,
isClickable: Boolean
) {
taskClickBtn.text = txt
taskClickBtn.setTextColor(txtColorId)
val background =
taskClickBtn.background as GradientDrawable //GradientDrawable是Drawable的子类
background.setColor(bgColorId)
taskClickBtn.isClickable = isClickable
}
override fun onDestroy() {
mViewModel.startOrStopCurrentTaskWithOrderLoop(false)
super.onDestroy()
}
private fun showDialog(){
if(dialog==null&&context!=null){
}
context?.let {
if(dialog==null) {
dialog = ItinerarySummaryDialog(it, true, R.style.summary_dialog)
}
dialog?.let { dialogInner ->
if(!dialogInner.isShowing){
dialogInner.show()
}
}
}
}
private fun dismissDialog(){
dialog?.let {
if(it.isShowing){
it.dismiss()
}
}
dialog = null
}
}

View File

@@ -1,490 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.task
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.module.status.MogoStatusManager
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.unmanned.CallerUnmannedListenerManager
import com.mogo.eagle.core.network.utils.GsonUtil
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.NetworkUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.biz.order.TaxiOrderStatusEnum
import com.mogo.och.common.module.manager.autopilot.location.OchLocationManager
import com.mogo.och.common.module.manager.autopilot.line.LineManager
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.common.module.manager.distance.TrajectoryAndDistanceManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.utils.ToastUtilsOch
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.data.bean.LineInfo
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.base.BaseViewModel
import com.mogo.och.unmanned.taxi.base.IUiIntent
import com.mogo.och.unmanned.taxi.bean.QueryCurrentTaskRespBean
import com.mogo.och.unmanned.taxi.bean.StartServiceRespBean
import com.mogo.och.unmanned.taxi.bean.TrajectoryListRespBean
import com.mogo.och.unmanned.taxi.callback.ITaxiCarServiceCallback
import com.mogo.och.unmanned.taxi.callback.ITaxiTaskWithOrderCallback
import com.mogo.och.unmanned.taxi.constant.TaskStatusEnum
import com.mogo.och.unmanned.taxi.constant.TaskTypeEnum
import com.mogo.och.unmanned.taxi.constant.TaxiUnmannedConst
import com.mogo.och.unmanned.taxi.network.TaxiTaskWithOrderServiceManager
import com.mogo.och.unmanned.taxi.ui.debug.DebugView
import com.mogo.och.unmanned.taxi.utils.TaxiTrajectoryManager
/**
* @author: wangmingjun
* @date: 2023/7/26
*/
class TaxiCurrentTaskViewModel : BaseViewModel<UnmannedState, TaskUiIntent>(),
ITaxiTaskWithOrderCallback, ITaxiCarServiceCallback {
private val TAG = SceneConstant.M_TAXI + "TaxiUnmannedViewModel"
init {
TaxiTaskModel.addTaskWithOrderListener(TAG, this)
TaxiTaskModel.setCarServiceCallback(this)
}
override fun onCleared() {
TaxiTaskModel.removeTaskWithOrderListener(TAG)
TaxiTaskModel.removeCarServiceCallback()
super.onCleared()
}
override fun initUiState(): UnmannedState {
return UnmannedState(TaskWithOrderUIState.Init)
}
override fun handleIntent(intent: IUiIntent) {
when (intent) {
is TaskUiIntent.StartTaskWithOrderLooper -> { //开始轮询
startOrStopCurrentTaskWithOrderLoop(true)
}
is TaskUiIntent.StartOrEndTakeOrder -> {//开始、暂停接单
TaxiTaskModel.updateCarServingStatus()
}
is TaskUiIntent.JumpPassengerCheck -> { //手动点击跳过乘客验证
jumpPassengerCheck()
}
is TaskUiIntent.JourneyCompleted -> { //点击服务完成
journeyCompleted()
}
is TaskUiIntent.CloseOrderByDriver -> {
closeOrderByDriver()
}
is TaskUiIntent.CancelOrder -> {// 取消订单, 暂未加取消类型和原因
cancelOrder(intent.type)
}
is TaskUiIntent.StartTask -> {
startTask()
}
}
}
fun startOrStopCurrentTaskWithOrderLoop(start: Boolean) {
d(TAG, "startOrStopCurrentTaskWithOrderLoop(): isStart=$start")
if (start) {
DebugView.printInfoMsg("[查询TaskWithOrder信息] start loop")
TaxiTaskModel.startQueryCurrentTaskWithOrderLoop()
} else {
DebugView.printInfoMsg("[查询TaskWithOrder信息] stop loop")
TaxiTaskModel.stopQueryCurrentTaskWithOrderLoop()
}
}
private fun cancelOrder(cancelType: Int) {
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
currentTaskWithOrder?.order?.also {
TaxiTaskModel.cancelOrder(it.orderNo, cancelType)
}
}
private fun jumpPassengerCheck() {
DebugView.printInfoMsg("[跳过乘客验证] 准备发送请求")
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
currentTaskWithOrder?.order?.also {
TaxiTaskWithOrderServiceManager.jumpPassengerCheck(AbsMogoApplication.getApp().applicationContext,
it.orderNo,
object : OchCommonServiceCallback<BaseData> {
override fun onSuccess(data: BaseData?) {
DebugView.printInfoMsg("[跳过乘客验证] 请求success")
d(TAG, "jumpPassengerCheck onSuccess:")
}
override fun onFail(code: Int, msg: String?) {
DebugView.printInfoMsg("[跳过乘客验证] 请求fail, code=$code, msg=$msg")
d(TAG, "jumpPassengerCheck onFail: code=$code, msg=$msg")
}
})
}
}
private fun journeyCompleted() {
DebugView.printInfoMsg("[服务完成] 准备发送请求")
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
currentTaskWithOrder?.order?.also {
TaxiTaskWithOrderServiceManager.orderCompleted(AbsMogoApplication.getApp().applicationContext,
it.orderNo,
object : OchCommonServiceCallback<BaseData> {
override fun onSuccess(data: BaseData?) {
DebugView.printInfoMsg("[服务完成] 请求success")
d(TAG, "journeyCompleted onSuccess")
}
override fun onFail(code: Int, msg: String?) {
DebugView.printInfoMsg("[服务完成] 请求fail, code=$code, msg=$msg")
d(TAG, "journeyCompleted onFail: code=$code, msg=$msg")
}
})
}
}
private fun closeOrderByDriver() {
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
currentTaskWithOrder?.order?.orderEndSite?.also {
TaxiTaskModel.submitArriveSite(it.siteId, true)
}
}
private fun startTask(isStartAutopilot: Boolean = true) {
if (!TaxiTaskModel.checkCurrentTaskCondition()) {
ToastUtils.showShort("无任务!")
return
}
TaxiTaskModel.getCurrentTaskWithOrder()?.let {
TaxiTaskModel.startTask(
if (it.order != null && it.order!!.orderStatus >= TaxiOrderStatusEnum.ArriveAtStart.code)
it.order!!.orderLine //当前若是启动的送驾任务 , 则使用订单信息的lineId
else
it.lineId
,isStartAutopilot)
}
}
private fun updateTaskAndOrderUi(currentTaskWithOrder: QueryCurrentTaskRespBean.Result?) {
d(
TAG, "updateTaskAndOrderUi: currentTaskWithOrder=${
GsonUtil.getGson().toJson(currentTaskWithOrder)
}"
)
sendUiState {
copy(
taskWithOrderUIState = TaskWithOrderUIState.TaskWithOrder(
currentTaskWithOrder
)
)
}
}
private fun updatePrepareTaskDelayUI(delayTime: Long, isStart: Boolean) {
d(TAG, "UpdatePrepareTaskDelay120SUI = $isStart")
sendUiState {
copy(
taskWithOrderUIState = TaskWithOrderUIState.UpdatePrepareTaskDelay(delayTime,
isStart
)
)
}
}
private fun updateDriveToNearestStationTaskUI(driveToNearestStationTask: StartServiceRespBean.Result?) {
d(TAG, "updateDriveToNearestStationTaskUI = ${driveToNearestStationTask?.toString()}")
sendUiState {
copy(
taskWithOrderUIState = TaskWithOrderUIState.TaskDriveToNearestStationTask(
driveToNearestStationTask
)
)
}
}
private fun updateOrderTripInfoUI(mileage: Float, duration: Int) {
d(TAG, "updateOrderTripInfoUI")
OchChainLogManager.writeChainLog("到达目的地计算距离和时间", "距离:${mileage} 时间:${duration}")
sendUiState {
copy(
taskWithOrderUIState = TaskWithOrderUIState.UpdateOrderTripInfo(
mileage, duration
)
)
}
}
private fun updateTaskTripInfoLocalCalculateUI(meters: Long, timeInSecond: Long) {
d(TAG, "UpdateTaskTripInfoLocalCalculateUI")
sendUiState {
copy(
taskWithOrderUIState = TaskWithOrderUIState.UpdateTaskTripLocalCalculateInfo(
meters, timeInSecond
)
)
}
}
override fun onTaskWithOrderQuerySuccess(timeMillis: Long) {
}
override fun onTaskWithOrderDataChanged(result: QueryCurrentTaskRespBean.Result?) {
d(TAG, "onTaskWithOrderChanged = result = " + GsonUtil.jsonFromObject(result))
DebugView.printInfoMsg("[查询TaskWithOrder信息] 更新数据, 刷新UI")
updateTaskAndOrderUi(result)
// 设置task执行相关状态切换模式时判断使用
if (result == null || result.taskType == TaskTypeEnum.None.code) {
MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, false)
LineManager.setLineInfo(null);
} else {
MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, true)
}
}
override fun onTaskStarted(result: QueryCurrentTaskRespBean.Result?) {
updateLocalCalculateStation(result)
if (result?.endSite != null){
TaxiTaskModel.setBeautificationMode(true)
updateAutopilotControlParameters()
}else{
clearDemoModeAndACParameters()
}
}
private fun updateLocalCalculateStation(result: QueryCurrentTaskRespBean.Result?) {
if (result?.startSite != null && result.endSite != null
) {
d(TAG, "updateLocalCalculateStation start")
val curTaskAndOrder = TaxiTaskModel.getCurrentTaskWithOrder() ?: return
if (curTaskAndOrder.startSite != null && curTaskAndOrder.endSite != null) {
val startStation = MogoLocation()
startStation.longitude = curTaskAndOrder.startSite!!.gcjLon
startStation.latitude = curTaskAndOrder.startSite!!.gcjLat
val endStation = MogoLocation()
endStation.longitude = curTaskAndOrder.endSite!!.gcjLon
endStation.latitude = curTaskAndOrder.endSite!!.gcjLat
TrajectoryAndDistanceManager.setStationPoint(
startStation,
endStation,
curTaskAndOrder.lineId
)
}
} else {
TaxiTaskModel.clearLocalCalculateStation()
}
}
/**
* 开始倒计时120s或者10s拉取任务
* 演练任务120s拉取
* 接驾任务10s拉取
*/
override fun onTaskCompleted(result: QueryCurrentTaskRespBean.Result?) {
d(TAG, "onTaskCompleted: ${result?.currentStatus}, siteId=${result?.endSite?.siteId}")
if (result?.order != null && result.servingStatus == 1){
if (result.taskType <= TaskTypeEnum.VirtualTask.code
&& result.order!!.orderStatus < TaxiOrderStatusEnum.ArriveAtStart.code) {
VoiceNotice.showNotice("已为您接到订单")
}
if (result.order!!.orderStatus == TaxiOrderStatusEnum.ArriveAtStart.code){
VoiceNotice.showNotice("已到达上车地点,等待乘客上车")
}
}
/**
* 1、有订单下(表示当前有订单或者未来有要执行的订单):
* 接驾任务需要立即拉取, 拉取时机在车辆前往上车点状态
* 送驾任务需要立即拉取, 拉取时机在乘客已上车状态
* 2、在没有订单情况下
* 若当前到站的是前往标定站点, 则45s去拉取任务
* 若当前是演练任务到站, 45s去拉取任务
* 若当前是接驾任务到站, 此情况肯定是有订单的, 则走1
* 若当前到站的是送驾任务, 不去拉取, 需等待司机点击服务完成按钮后拉取
*/
if (result?.order != null){ //接到订单情况下
if (QueryCurrentTaskRespBean.isOrderOnTheWayToStart(result)){ //接驾任务拉取
TaxiTaskModel.startPrepareTaskDelay(TaxiUnmannedConst.START_PREPARE_TO_START_TASK_INTERVAL,
result?.endSite!!.siteId)
}else if (QueryCurrentTaskRespBean.isOrderUserArriveAtStart(result)) { //送驾任务拉取
TaxiTaskModel.startPrepareTaskDelay(0, result?.endSite!!.siteId)
}else{ // 在已经接到订单的其他情况下, 取消倒计时任务拉取
TaxiTaskModel.removePrepareTaskDelay()
}
}else{ //演练任务拉取 6.2.0使用配置的时间拉取, 默认45s
TaxiTaskModel.startPrepareTaskDelay(
CallerUnmannedListenerManager.getVirtualTaskPullTaskIntervalF() * 1000L, result?.endSite!!.siteId)
}
clearDemoModeAndACParameters()
}
override fun onTaskTrajectoryDataChanged(data: TrajectoryListRespBean?) {
TaxiTrajectoryManager.getInstance().syncTrajectoryInfo() //同步轨迹信息
}
override fun onOrderCancel() {
VoiceNotice.showNotice("已取消行程")
//取消自驾,D档位会溜车 map3.6.0 修改
TaxiTaskModel.cancelAutopilot()
// 设置task执行相关状态切换模式时判断使用
MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, false)
LineManager.setLineInfo(null);
}
override fun onOrderArriveAtEnd(orderNo: String) {
TaxiTaskModel.queryOrderByOrderNo(orderNo)
}
/**
* 更新总全程信息(公里和分钟), 后端返回的数据
*/
override fun onOrderTripInfoChanged(mileage: Float, duration: Int) {
updateOrderTripInfoUI(mileage, duration)
}
override fun onOrderJourneyCompleted() {
updateTaskAndOrderUi(null)
//获取新的任务
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
currentTaskWithOrder?.endSite?.also {//使用配置的时间拉取, 默认是45s
TaxiTaskModel.startPrepareTaskDelay(CallerUnmannedListenerManager.getVirtualTaskPullTaskIntervalF() * 1000L,
it.siteId)
}
// 设置task执行相关状态切换模式时判断使用
MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, false)
LineManager.setLineInfo(null);
}
override fun onStartAutopilot(postDelayTime: Long) {
UiThreadHandler.postDelayed(startTaskRunnable, postDelayTime) // 5s后或者倒计时结束开启自驾, 状态流转
}
private val startTaskRunnable: Runnable = Runnable {
startTask() //状态流转
VoiceNotice.showNotice("车辆正在自动开启自动驾驶")
}
/**
* 主动请求平行驾驶, 停止启动自驾命令, 任务状态需向下流转
*/
override fun onStopAutopilot() {
UiThreadHandler.removeCallbacks(startTaskRunnable)
if (!TaxiTaskModel.checkCurrentTaskCondition()) {
d(TAG, "onStopAutopilot: 无任务无需流转状态")
return
}
startTask(false)
}
override fun onPauseStartAutopilot() {
UiThreadHandler.removeCallbacks(startTaskRunnable)
}
/**
* 开始倒计时120s或者10s拉取任务
* 演练任务120s拉取
* 接驾任务10s拉取
*/
override fun onStartPrepareTaskUI(delayTime: Long, isStart: Boolean) {
updatePrepareTaskDelayUI(delayTime, isStart)
}
/**
* 更新本次任务行程信息, 本地计算的数据
*/
override fun onTaskTripInfoLocalCalculateChanged(meters: Long, timeInSecond: Long) {
updateTaskTripInfoLocalCalculateUI(meters, timeInSecond)
}
override fun onCarEndServiceSuccess(
driveToNearestStationTask: StartServiceRespBean.Result?,
currentTaskWithOrder: QueryCurrentTaskRespBean.Result?
) {
if (currentTaskWithOrder == null) return
if (currentTaskWithOrder.currentStatus < TaskStatusEnum.CompleteTask.code //任务未完成
&& currentTaskWithOrder.currentStatus > TaskStatusEnum.None.code // 暂停接单后查询到任务状态是0, 代表没任务
|| currentTaskWithOrder.order != null) {// 有订单未完成
VoiceNotice.showNotice("暂停接单啦!要完成当前订单哦")
} else {
VoiceNotice.showNotice("暂停接单啦")
updateDriveToNearestStationTaskUI(driveToNearestStationTask)
}
}
override fun onCarEndServiceFailed(code: Int, msg: String) {
ToastUtilsOch.showWithCodeMessage(code, msg)
}
override fun onCarEndServiceError() {
val context = AbsMogoApplication.getApp().applicationContext
if (!NetworkUtils.isConnected(context)) {
ToastUtils.showShort(context.getString(R.string.network_error_tip))
} else {
ToastUtils.showShort(context.getString(R.string.request_error_tip))
}
}
override fun onCarStartServiceSuccess(
driveToNearestStationTask: StartServiceRespBean.Result?,
currentTaskWithOrder: QueryCurrentTaskRespBean.Result?
) {
VoiceNotice.showNotice("开始接单啦")
updateDriveToNearestStationTaskUI(driveToNearestStationTask)
}
override fun onCarStartServiceFailed(code: Int, msg: String) {
val gcJ02Location = OchLocationManager.getGCJ02Location()
ToastUtilsOch.showWithCodeMessage(
code,
"$msg curLatitude = ${gcJ02Location.latitude}" + " curLongitude = ${gcJ02Location.longitude}"
)
}
override fun onCarStartServiceError() {
val context = AbsMogoApplication.getApp().applicationContext
if (!NetworkUtils.isConnected(context)) {
ToastUtils.showShort(context.getString(R.string.network_error_tip))
} else {
ToastUtils.showShort(context.getString(R.string.request_error_tip))
}
}
override fun onStartTaskFail() {
}
private fun clearDemoModeAndACParameters(){
if (FunctionBuildConfig.isDemoMode) {
d(TAG, "setIPCDemoModefalse")
CallerAutoPilotControlManager.setIPCDemoMode(false)
}
TaxiTaskModel.clearAutopilotControlParameters()
}
/**
* 将业务订单信息保存,鹰眼可取用
*/
private fun updateAutopilotControlParameters() {
val parameters = TaxiTaskModel.initAutopilotControlParameters()
if (null == parameters) {
CallerLogger.e(TAG, "AutopilotControlParameters is empty.")
return
}
d(TAG, "AutopilotControlParameters is update.")
DebugView.printInfoMsg("[启自驾] updateAutopilotControlParameters调用成功")
CallerAutoPilotStatusListenerManager.updateAutopilotControlParameters(parameters)
}
}

View File

@@ -1,142 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.task
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.view.View
import androidx.core.content.ContextCompat
import com.mogo.commons.mvp.BaseFragment
import com.mogo.eagle.core.function.main.MainMoGoApplication
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.bean.OrderDetail
import com.mogo.och.unmanned.taxi.bean.QueryCurrentTaskRespBean
import com.mogo.och.unmanned.taxi.constant.TaskStatusEnum
import com.mogo.och.unmanned.taxi.constant.TaskTypeEnum
import com.mogo.och.unmanned.taxi.ui.task.cancleorder.CancleOrderView
import com.mogo.och.unmanned.taxi.utils.TaskUtils
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.cancelOrder
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.endStationName
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.mCurrentTaskLayout
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.naviToEnd
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.naviToStart
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.noTaskData
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.orderPhoneAndNum
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.startStationName
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.taskClickBtn
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.taskOtherInfo
import kotlinx.android.synthetic.main.unmanned_task_fragment_current.taskTypeTv
/**
* @author: wangmingjun
* @date: 2023/7/24
*/
class TaxiNextTaskFragment : BaseFragment() {
companion object {
val TAG = SceneConstant.M_TAXI + javaClass.simpleName
fun newInstance(): TaxiNextTaskFragment {
val args = Bundle()
val fragment = TaxiNextTaskFragment()
fragment.arguments = args
return fragment
}
}
override fun getLayoutId(): Int {
return R.layout.unmanned_task_fragment_current
}
override fun getTagName(): String {
return javaClass.simpleName
}
override fun initViews() {
cancelOrder.onClick { //取消待服务订单
val currentWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
if (currentWithOrder?.order != null) {
val order = currentWithOrder.order
activity?.also {
context?.let {
CancleOrderView.showDialog(it)
}
}
}
}
showNoNextTaskView()
}
fun onTaskDataChanged(taskWithOrder: QueryCurrentTaskRespBean.Result?) {
if (taskWithOrder?.order == null) {
showNoNextTaskView()
return
}
if (taskWithOrder.taskType == TaskTypeEnum.VirtualTask.code &&
taskWithOrder.currentStatus != TaskStatusEnum.CompleteTask.code
) {
val order = taskWithOrder.order
updateTaskUI(order!!)
} else {
showNoNextTaskView()
}
}
private fun updateTaskUI(order: OrderDetail) {
showNextTaskView()
taskOtherInfo.visibility = View.GONE
naviToStart.visibility = View.GONE
naviToEnd.visibility = View.GONE
orderPhoneAndNum.text =
TaskUtils.getNextTaskPhoneNumAndPassengerCountHtml(
order.bookingUserPhone,
order.passengerSize
)
order.orderStartSite?.let {
startStationName.text = it.siteName
}
order.orderEndSite?.let {
endStationName.text = it.siteName
}
taskTypeTv.text = resources.getString(R.string.task_order)
taskTypeTv.background =
ContextCompat.getDrawable(
MainMoGoApplication.getApp().applicationContext,
R.drawable.task_order_type_btn_bg
)
updateTaskContainerBottomBtn(
getString(R.string.waiting_server),
Color.parseColor("#4DFFFFFF"),
Color.parseColor("#4D1D5EF3"),
false
)
}
private fun updateTaskContainerBottomBtn(
txt: String?,
txtColorId: Int,
bgColorId: Int,
isClickable: Boolean
) {
taskClickBtn.text = txt
taskClickBtn.setTextColor(txtColorId)
val background =
taskClickBtn.background as GradientDrawable //GradientDrawable是Drawable的子类
background.setColor(bgColorId)
taskClickBtn.isClickable = isClickable
}
private fun showNoNextTaskView() {
noTaskData.visibility = View.VISIBLE
mCurrentTaskLayout.visibility = View.GONE
}
private fun showNextTaskView() {
noTaskData.visibility = View.GONE
mCurrentTaskLayout.visibility = View.VISIBLE
}
}

View File

@@ -1,201 +0,0 @@
package com.mogo.och.unmanned.taxi.ui.task
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
import com.google.android.material.tabs.TabLayout
import com.mogo.commons.mvp.BaseFragment
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.och.common.module.utils.FlowBus
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.bean.QueryCurrentTaskRespBean
import com.mogo.och.unmanned.taxi.constant.TaxiDriverEventConst
import kotlinx.android.synthetic.main.unmanned_taxi_server_orders_panel.module_och_taxi_tab
import kotlinx.android.synthetic.main.unmanned_taxi_server_orders_panel.module_och_taxi_view_pager
import kotlinx.android.synthetic.main.unmanned_taxi_server_orders_panel.wait_order_num
import me.jessyan.autosize.utils.AutoSizeUtils
/**
* @author: wangmingjun
* @date: 2023/7/25
* @desc: 司机端任务fragment 容器,展示了“进行中”和“待服务”的任务信息
* 任务:可以理解为对应的是一个自动驾驶任务
* 任务类型:演练任务 / 接驾任务 / 送驾任务
* DriveToNearestStationTask: 一种特殊任务,人工驾驶去最近的站点任务。每次 开启接单 后后端都会返回离当前最近的站点,车辆需要
* 开到此站点后才能进入无人化接单的整体流程
* 订单是面向C端小程序的一个概念用户下单后产生的是一个订单后端会将一个订单分解成 接驾任务和送驾任务 并派发到
* 车端来执行
* 任务和订单的对应1.如果是一个演练任务是后端自动生成的没有和C端订单挂钩
* 2.如果是一个接驾任务 或 送驾任务是和一个实际的C端订单对应的
*/
class TaxiTaskTabFragment : BaseFragment() {
companion object {
const val TAG = "TaxiTaskTabFragment"
const val TAB_POSITION_CURRENT = 0
const val TAB_POSITION_NEXT = 1
val mTabTitles = arrayOf("进行中", "待服务")
fun newInstance(): TaxiTaskTabFragment {
val args = Bundle()
val fragment = TaxiTaskTabFragment()
fragment.arguments = args
return fragment
}
}
private val mFragments: MutableList<Fragment> = ArrayList()
private var currentTaskFragment: TaxiCurrentTaskFragment? = null
private var nextTaskFragment: TaxiNextTaskFragment? = null
override fun getLayoutId(): Int {
return R.layout.unmanned_taxi_server_orders_panel
}
override fun getTagName(): String {
return this.javaClass.simpleName
}
override fun initViews() {
initTaskTab()
initEventBus()
}
private fun initTaskTab() {
for (position in mTabTitles.indices) {
val tab = module_och_taxi_tab.newTab()
tab.view.setBackgroundColor(Color.parseColor("#00000000"))
val tabView =
View.inflate(activity, R.layout.unmanned_taxi_tab_item_custom, null) as TextView
tabView.text = mTabTitles[position]
tabView.height = AutoSizeUtils.dp2px(context, 115f)
tab.customView = tabView
if (TAB_POSITION_CURRENT == position) {
module_och_taxi_tab.addTab(tab, true)
changeTabLayoutUI(tab, true)
currentTaskFragment = TaxiCurrentTaskFragment.newInstance()
mFragments.add(currentTaskFragment!!)
} else if (TAB_POSITION_NEXT == position) {
module_och_taxi_tab.addTab(tab)
changeTabLayoutUI(tab, false)
nextTaskFragment = TaxiNextTaskFragment.newInstance()
mFragments.add(nextTaskFragment!!)
}
}
d(SceneConstant.M_TAXI + TAG, "activity=$activity")
module_och_taxi_tab.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
module_och_taxi_view_pager.currentItem = tab.position
changeTabLayoutUI(tab, true)
}
override fun onTabUnselected(tab: TabLayout.Tab) {
changeTabLayoutUI(tab, false)
}
override fun onTabReselected(tab: TabLayout.Tab) {}
})
module_och_taxi_view_pager.addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
}
override fun onPageSelected(position: Int) {
module_och_taxi_tab.getTabAt(position)!!.select()
}
override fun onPageScrollStateChanged(state: Int) {}
})
module_och_taxi_view_pager.adapter = TaskTabFragmentAdapter(
childFragmentManager,
FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
)
}
private fun changeTabLayoutUI(tab: TabLayout.Tab, isSelected: Boolean) {
val textView = tab.customView!!.findViewById<View>(R.id.tab_title) as TextView
if (isSelected) {
textView.background =
ContextCompat.getDrawable(requireContext(), R.drawable.taxi_driver_tab_item_bg)
textView.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
AutoSizeUtils.dp2px(context, 40f).toFloat()
)
textView.typeface = Typeface.defaultFromStyle(Typeface.BOLD)
textView.setTextColor(Color.parseColor("#FFFFFF"))
d(SceneConstant.M_TAXI + TAG, "SelectTv = " + textView.text)
} else {
textView.background = null
textView.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
AutoSizeUtils.dp2px(context, 36f).toFloat()
)
textView.typeface = Typeface.defaultFromStyle(Typeface.NORMAL)
textView.setTextColor(Color.parseColor("#CCD4F5"))
d(SceneConstant.M_TAXI + TAG, "unSelectTv = " + textView.text)
}
}
internal inner class TaskTabFragmentAdapter(
fragmentManager: FragmentManager,
behavior: Int
) :
FragmentPagerAdapter(fragmentManager, behavior) {
override fun getItem(position: Int): Fragment {
d(
SceneConstant.M_TAXI + TAG,
"getItem=$position"
)
return mFragments[position]
}
override fun getCount(): Int {
return mFragments.size
}
override fun getPageTitle(position: Int): CharSequence {
d(
SceneConstant.M_TAXI + TAG,
"getPageTitle=$position"
)
return mTabTitles[position]
}
}
private fun initEventBus() {
FlowBus.with<Boolean>(TaxiDriverEventConst.TabFragmentEvent.EVENT_TYPE_SHOW_RED_POINT)
.register(this) { show ->
wait_order_num.visibility = if (show) View.VISIBLE else View.GONE
}
FlowBus.with<QueryCurrentTaskRespBean.Result?>(TaxiDriverEventConst.TabFragmentEvent.EVENT_TYPE_TASK_WITH_ORDER_CHANGED)
.register(this) { taskWithOrder ->
nextTaskFragment?.onTaskDataChanged(taskWithOrder)
}
}
fun onNaviToEndStationByAMap(isShow: Boolean) {
currentTaskFragment?.onNaviToEndStationByAmap(isShow)
}
fun onCarTakeOrderStatusChanged() {
currentTaskFragment?.onCarTakeOrderStatusChanged()
}
}

View File

@@ -14,6 +14,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.util.NetworkUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.biz.login.LoginStatusManager
import com.mogo.och.common.module.biz.order.TaxiOrderStatusEnum
import com.mogo.och.common.module.manager.autopilot.line.LineManager
import com.mogo.och.common.module.manager.autopilot.location.OchLocationManager
@@ -167,6 +168,8 @@ class ItineraryCurrentModel : BaseViewModel<UnmannedState, TaskUiIntent>(),
}
}
private fun closeOrderByDriver() {
val currentTaskWithOrder = TaxiTaskModel.getCurrentTaskWithOrder()
currentTaskWithOrder?.order?.orderEndSite?.also {
@@ -509,6 +512,24 @@ class ItineraryCurrentModel : BaseViewModel<UnmannedState, TaskUiIntent>(),
CallerAutoPilotStatusListenerManager.updateAutopilotControlParameters(parameters)
}
fun cancleTask() {
DebugView.printInfoMsg("[车辆复位] 准备发送请求")
TaxiTaskWithOrderServiceManager.resetInit(
AbsMogoApplication.getApp().applicationContext,
object : OchCommonServiceCallback<BaseData> {
override fun onSuccess(data: BaseData?) {
DebugView.printInfoMsg("[车辆复位] 请求success")
LoginStatusManager.queryLoginStatusByNet()
VoiceNotice.showNotice("暂停接单啦!");
d(TAG, "journeyCompleted onSuccess")
}
override fun onFail(code: Int, msg: String?) {
DebugView.printInfoMsg("[车辆复位] 请求fail, code=$code, msg=$msg")
d(TAG, "journeyCompleted onFail: code=$code, msg=$msg")
}
})
}
interface SwtichLineViewCallback {

View File

@@ -33,6 +33,7 @@ import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.common.module.wigets.CommonSlideView
import com.mogo.och.common.module.wigets.dialog.CommonDialogStatus
import com.mogo.och.common.module.wigets.dialog.CommonDialogView
import com.mogo.och.unmanned.taxi.R
import com.mogo.och.unmanned.taxi.TaxiUnmannedDriverProvider
import com.mogo.och.unmanned.taxi.bean.OrderDetail
@@ -57,6 +58,7 @@ import kotlinx.android.synthetic.main.unmanned_itinerary_current.view.actv_end_o
import kotlinx.android.synthetic.main.unmanned_itinerary_current.view.actv_order_phone
import kotlinx.android.synthetic.main.unmanned_itinerary_current.view.actv_submit_task
import kotlinx.android.synthetic.main.unmanned_itinerary_current.view.cancelOrder
import kotlinx.android.synthetic.main.unmanned_itinerary_current.view.cancelTask
import kotlinx.android.synthetic.main.unmanned_itinerary_current.view.commonSlideViewStartServer
import kotlinx.android.synthetic.main.unmanned_itinerary_current.view.gourp_order
import kotlinx.android.synthetic.main.unmanned_itinerary_current.view.group_itinerary_info
@@ -295,6 +297,7 @@ class ItineraryCurrentView: ConstraintLayout, ItineraryCurrentModel.SwtichLineVi
group_itinerary_info.visibility = GONE
include_empty.visibility = VISIBLE
prepareTaskCountdownTv.visibility = GONE
cancelTask.visibility = View.GONE
actv_end_order.visibility = GONE
commonSlideViewStartServer.visibility = GONE
@@ -305,6 +308,7 @@ class ItineraryCurrentView: ConstraintLayout, ItineraryCurrentModel.SwtichLineVi
private fun initOnClickListener() {
naviToStart.setOnClickListener(this)
naviToEnd.setOnClickListener(this)
cancelTask.setOnClickListener(this)
cancelOrder.setOnClickListener(this)
taskStatus.setOnClickListener(this)
@@ -412,6 +416,26 @@ class ItineraryCurrentView: ConstraintLayout, ItineraryCurrentModel.SwtichLineVi
naviToEnd.id -> {
showNaviToEndStationFragment()
}
cancelTask.id -> {
val builder = CommonDialogStatus.Builder()
val closeLineConfirmDialog = builder
.title(ResourcesUtils.getString(R.string.common_dialog_title))
.tips(ResourcesUtils.getString(R.string.taxi_dialog_cancle_task))
.confirmStr(ResourcesUtils.getString(R.string.common_dialog_confirm))
.cancelStr(ResourcesUtils.getString(R.string.common_dialog_cancel))
.status(CommonDialogStatus.Status.ask)
.build(context)
closeLineConfirmDialog.setClickListener(object : CommonDialogStatus.ClickListener {
override fun confirm() {
viewModel?.cancleTask()
}
override fun cancel() {
closeLineConfirmDialog.dismiss()
}
})
closeLineConfirmDialog.show()
}
}
}
@@ -454,6 +478,7 @@ class ItineraryCurrentView: ConstraintLayout, ItineraryCurrentModel.SwtichLineVi
aciv_task_type_exercise.visibility = View.GONE
// 轨迹标识
trajectoryType.visibility = View.GONE
cancelTask.visibility = View.GONE
actv_end_order.visibility = GONE
@@ -504,6 +529,8 @@ class ItineraryCurrentView: ConstraintLayout, ItineraryCurrentModel.SwtichLineVi
== TaxiOrderStatusEnum.OnTheWayToEnd.code
) View.VISIBLE else View.GONE
cancelTask.visibility = View.GONE
updatePrepareTaskDelayUI(0, false)
orderPhoneAndNum.text = TaskUtils.getCurrentTaskPhoneNumAndPassengerCountHtml(
@@ -636,7 +663,7 @@ class ItineraryCurrentView: ConstraintLayout, ItineraryCurrentModel.SwtichLineVi
taskStatus.text = resources.getString(R.string.task_start_end_site)
aciv_task_type_exercise.setImageResource(R.drawable.taxi_task_exercise)
cancelTask.visibility = VISIBLE
startStationName.text = startSite.siteName
endStationName.text = endSite.siteName
@@ -870,5 +897,4 @@ class ItineraryCurrentView: ConstraintLayout, ItineraryCurrentModel.SwtichLineVi
commonSlideViewStartServer.reset()
}
}

View File

@@ -141,6 +141,17 @@
android:layout_width="@dimen/dp_46"
android:layout_height="@dimen/dp_46"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/cancelTask"
app:layout_constraintTop_toTopOf="@+id/startStationName"
app:layout_constraintBottom_toBottomOf="@+id/startStationName"
app:layout_constraintEnd_toEndOf="@+id/v_bg_itinerary_info"
android:visibility="gone"
android:layout_marginEnd="@dimen/dp_36"
android:src="@drawable/taxi_task_close"
android:layout_width="@dimen/dp_46"
android:layout_height="@dimen/dp_46"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/actv_distance_end"
android:text="5.2公里"

View File

@@ -76,5 +76,7 @@
<string name="routing_feedback_result_btn_not_sure">线路不可用</string>
<string name="routing_feedback_result_hint">路线验证结束啦!点击下方按钮反馈验证结果吧</string>
<string name="taxi_dialog_cancle_task">您确认要结束任务吗?</string>
<!-- endregion -->
</resources>