Commit 0ee5f4d1 authored by timel's avatar timel

feat: valtio store logic 90%, ui/message

parent 602ea114
......@@ -6,8 +6,15 @@ import { sendSurrender } from "@/api/ocgcore/ocgHelper";
import { useAppSelector } from "@/hook";
import { selectUnimplemented } from "@/reducers/duel/mod";
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
export const Alert = () => {
const unimplemented = useAppSelector(selectUnimplemented);
// const unimplemented = useAppSelector(selectUnimplemented);
const matSnap = useSnapshot(matStore);
const unimplemented = matSnap.unimplemented;
const navigate = useNavigate();
return (
......
......@@ -14,23 +14,37 @@ import {
} from "@/reducers/duel/modal/mod";
import { store } from "@/store";
import {
messageStore,
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities,
} from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig();
const CARD_WIDTH = 100;
const { cardListModal } = messageStore;
export const CardListModal = () => {
const dispatch = store.dispatch;
const isOpen = useAppSelector(selectCardListModalIsOpen);
const list = useAppSelector(selectCardListModalInfo);
// const isOpen = useAppSelector(selectCardListModalIsOpen);
// const list = useAppSelector(selectCardListModalInfo);
const snapCardListModal = useSnapshot(cardListModal);
const isOpen = snapCardListModal.isOpen;
const list = snapCardListModal.list;
const handleOkOrCancel = () => {
dispatch(setCardListModalIsOpen(false));
cardListModal.isOpen = false;
};
return (
<Drawer open={isOpen} onClose={handleOkOrCancel}>
<List
itemLayout="horizontal"
// @ts-ignore 报错是因为类型不可变,实际上是没问题的
dataSource={list}
renderItem={(item) => (
<List.Item
......@@ -42,6 +56,10 @@ export const CardListModal = () => {
dispatch(setCardListModalIsOpen(false));
dispatch(clearAllIdleInteractivities(0));
dispatch(clearAllIdleInteractivities(1));
cardListModal.isOpen = false;
FIXME_clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(1);
}}
>
{interactivy.desc}
......
......@@ -27,14 +27,28 @@ import {
Type2StringCodeMap,
} from "../../../common";
import {
messageStore,
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities,
} from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig();
const { Meta } = Card;
const CARD_WIDTH = 240;
const { cardModal } = messageStore;
export const CardModal = () => {
const snapCardModal = useSnapshot(cardModal);
const dispatch = store.dispatch;
const isOpen = useAppSelector(selectCardModalIsOpen);
const meta = useAppSelector(selectCardModalMeta);
// const isOpen = useAppSelector(selectCardModalIsOpen);
// const meta = useAppSelector(selectCardModalMeta);
const isOpen = snapCardModal.isOpen;
const meta = snapCardModal.meta;
const name = meta?.text.name;
const types = meta?.data.type;
const race = meta?.data.race;
......@@ -43,14 +57,19 @@ export const CardModal = () => {
const desc = meta?.text.desc;
const atk = meta?.data.atk;
const def = meta?.data.def;
const counters = useAppSelector(selectCardModalCounters);
// const counters = useAppSelector(selectCardModalCounters);
const counters = snapCardModal.counters;
const imgUrl = meta?.id
? `${NeosConfig.cardImgUrl}/${meta.id}.jpg`
: undefined;
const interactivies = useAppSelector(selectCardModalInteractivies);
// const interactivies = useAppSelector(selectCardModalInteractivies);
const interactivies = snapCardModal.interactivies;
const handleOkOrCancel = () => {
dispatch(setCardModalIsOpen(false));
cardModal.isOpen = false;
};
return (
......@@ -79,6 +98,9 @@ export const CardModal = () => {
dispatch(setCardModalIsOpen(false));
dispatch(clearAllIdleInteractivities(0));
dispatch(clearAllIdleInteractivities(1));
cardModal.isOpen = false;
FIXME_clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(1);
}}
>
{interactive.desc}
......
......@@ -26,18 +26,36 @@ import { store } from "@/store";
import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig();
const { checkCardModal } = messageStore;
export const CheckCardModal = () => {
const snapCheckCardModal = useSnapshot(checkCardModal);
const dispatch = store.dispatch;
const isOpen = useAppSelector(selectCheckCardModalIsOpen);
const { min, max } = useAppSelector(selectCheckCardModalMinMax);
const tabs = useAppSelector(selectCheckCardModalTags);
const onSubmit = useAppSelector(selectCheckCardModalOnSubmit);
const cancelAble = useAppSelector(selectCheckCardModalCancelAble);
const cancelResponse = useAppSelector(selectCheckCardModalCacnelResponse);
// const isOpen = useAppSelector(selectCheckCardModalIsOpen);
// const { min, max } = useAppSelector(selectCheckCardModalMinMax);
// const tabs = useAppSelector(selectCheckCardModalTags);
// const onSubmit = useAppSelector(selectCheckCardModalOnSubmit);
// const cancelAble = useAppSelector(selectCheckCardModalCancelAble);
// const cancelResponse = useAppSelector(selectCheckCardModalCacnelResponse);
const isOpen = snapCheckCardModal.isOpen;
const min = snapCheckCardModal.selectMin ?? 0;
const max = snapCheckCardModal.selectMax ?? 10;
const tabs = snapCheckCardModal.tags;
const onSubmit = snapCheckCardModal.onSubmit;
const cancelAble = snapCheckCardModal.cancelAble;
const cancelResponse = snapCheckCardModal.cancelResponse;
const [response, setResponse] = useState<number[]>([]);
const defaultValue: number[] = [];
const hint = useAppSelector(selectHint);
// const hint = useAppSelector(selectHint);
const hint = useSnapshot(matStore.hint);
const preHintMsg = hint?.esHint || "";
const selectHintMsg = hint?.esSelectHint || "请选择卡片";
......@@ -60,6 +78,21 @@ export const CheckCardModal = () => {
}
};
const FIXME_resetCheckCardModal = () => {
// state.modalState.checkCardModal.isOpen = false;
// state.modalState.checkCardModal.selectMin = undefined;
// state.modalState.checkCardModal.selectMax = undefined;
// state.modalState.checkCardModal.cancelAble = false;
// state.modalState.checkCardModal.cancelResponse = undefined;
// state.modalState.checkCardModal.tags = [];
checkCardModal.isOpen = false;
checkCardModal.selectMin = undefined;
checkCardModal.selectMax = undefined;
checkCardModal.cancelAble = false;
checkCardModal.cancelResponse = undefined;
checkCardModal.tags = [];
};
return (
<DragModal
title={`${preHintMsg} ${selectHintMsg} ${min}-${max}`}
......@@ -73,6 +106,8 @@ export const CheckCardModal = () => {
sendResponseHandler(onSubmit, response);
dispatch(setCheckCardModalIsOpen(false));
dispatch(resetCheckCardModal());
checkCardModal.isOpen = false;
FIXME_resetCheckCardModal();
}}
onFocus={() => {}}
onBlur={() => {}}
......@@ -87,6 +122,8 @@ export const CheckCardModal = () => {
}
dispatch(setCheckCardModalIsOpen(false));
dispatch(resetCheckCardModal());
checkCardModal.isOpen = false;
FIXME_resetCheckCardModal();
}}
onFocus={() => {}}
onBlur={() => {}}
......
......@@ -24,27 +24,62 @@ import { store } from "@/store";
import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { checkCardModalV2 } = messageStore;
const NeosConfig = useConfig();
export const CheckCardModalV2 = () => {
const snapCheckCardModalV2 = useSnapshot(checkCardModalV2);
const dispatch = store.dispatch;
const isOpen = useAppSelector(selectCheckCardModalV2IsOpen);
const { min, max } = useAppSelector(selectCheckCardModalV2MinMax);
const cancelable = useAppSelector(selectCheckCardModalV2CancelAble);
const finishable = useAppSelector(selectCheckCardModalV2FinishAble);
const selectableOptions = useAppSelector(
selectCheckCardModalV2SelectAbleOptions
);
const selectedOptions = useAppSelector(selectCheckCardModalV2SelectedOptions);
const responseable = useAppSelector(selectCheckCardModalV2ResponseAble);
const hint = useAppSelector(selectHint);
// const isOpen = useAppSelector(selectCheckCardModalV2IsOpen);
// const { min, max } = useAppSelector(selectCheckCardModalV2MinMax);
// const cancelable = useAppSelector(selectCheckCardModalV2CancelAble);
// const finishable = useAppSelector(selectCheckCardModalV2FinishAble);
// const selectableOptions = useAppSelector(
// selectCheckCardModalV2SelectAbleOptions
// );
// const selectedOptions = useAppSelector(selectCheckCardModalV2SelectedOptions);
// const responseable = useAppSelector(selectCheckCardModalV2ResponseAble);
// const hint = useAppSelector(selectHint);
const isOpen = snapCheckCardModalV2.isOpen;
const min = snapCheckCardModalV2.selectMin ?? 0;
const max = snapCheckCardModalV2.selectMax ?? 10;
const cancelable = snapCheckCardModalV2.cancelAble;
const finishable = snapCheckCardModalV2.finishAble;
const selectableOptions = snapCheckCardModalV2.selectableOptions;
const selectedOptions = snapCheckCardModalV2.selectedOptions;
const responseable = snapCheckCardModalV2.responseable;
const hint = useSnapshot(matStore.hint);
const preHintMsg = hint?.esHint || "";
const selectHintMsg = hint?.esSelectHint || "请选择卡片";
const FIXME_resetCheckCardModalV2 = () => {
// modalState.isOpen = false;
// modalState.finishAble = false;
// modalState.cancelAble = false;
// modalState.responseable = false;
// modalState.selectableOptions = [];
// modalState.selectedOptions = [];
checkCardModalV2.isOpen = false;
checkCardModalV2.finishAble = false;
checkCardModalV2.cancelAble = false;
checkCardModalV2.responseable = false;
checkCardModalV2.selectableOptions = [];
checkCardModalV2.selectedOptions = [];
};
const onFinishOrCancel = () => {
sendSelectUnselectCardResponse({ cancel_or_finish: true });
dispatch(setCheckCardModalV2IsOpen(false));
dispatch(resetCheckCardModalV2());
dispatch(setCheckCardModalV2ResponseAble(false));
checkCardModalV2.isOpen = false;
checkCardModalV2.responseable = false;
FIXME_resetCheckCardModalV2();
};
return (
......@@ -79,6 +114,8 @@ export const CheckCardModalV2 = () => {
// @ts-ignore
sendSelectUnselectCardResponse({ selected_ptr: value });
dispatch(setCheckCardModalV2ResponseAble(false));
checkCardModalV2.isOpen = false;
checkCardModalV2.responseable = false;
}
}}
>
......
......@@ -16,19 +16,36 @@ import { store } from "@/store";
import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig();
const { checkCardModalV3 } = messageStore;
export const CheckCardModalV3 = () => {
const snapCheckCardModalV3 = useSnapshot(checkCardModalV3);
const dispatch = store.dispatch;
const state = useAppSelector(selectCheckCardModalV3);
const isOpen = state.isOpen;
const min = state.selectMin || 0;
const max = state.selectMax || 0;
const mustSelectOptions = state.mustSelectList;
const selectAbleOptions = state.selectAbleList;
// const state = useAppSelector(selectCheckCardModalV3);
// const isOpen = state.isOpen;
// const min = state.selectMin || 0;
// const max = state.selectMax || 0;
// const mustSelectOptions = state.mustSelectList;
// const selectAbleOptions = state.selectAbleList;
// const overflow = state.overflow;
// const LevelSum = state.allLevel;
const isOpen = snapCheckCardModalV3.isOpen;
const min = snapCheckCardModalV3.selectMin || 0;
const max = snapCheckCardModalV3.selectMax || 0;
const mustSelectOptions = snapCheckCardModalV3.mustSelectList;
const selectAbleOptions = snapCheckCardModalV3.selectAbleList;
const overflow = snapCheckCardModalV3.overflow;
const LevelSum = snapCheckCardModalV3.allLevel;
const [selectedOptions, setSelectedOptions] = useState([]);
const overflow = state.overflow;
const LevelSum = state.allLevel;
const Level1Sum = mustSelectOptions
.concat(selectedOptions)
.map((option) => option.level1)
......@@ -37,7 +54,8 @@ export const CheckCardModalV3 = () => {
.concat(selectedOptions)
.map((option) => option.level2)
.reduce((sum, current) => sum + current, 0);
const hint = useAppSelector(selectHint);
// const hint = useAppSelector(selectHint);
const hint = useSnapshot(matStore.hint);
const preHintMsg = hint?.esHint || "";
const selectHintMsg = hint?.esSelectHint || "请选择卡片";
......@@ -54,6 +72,21 @@ export const CheckCardModalV3 = () => {
dispatch(setCheckCardModalV3IsOpen(false));
dispatch(resetCheckCardModalV3());
dispatch(setCheckCardModalV3ResponseAble(false));
checkCardModalV3.isOpen = false;
checkCardModalV3.responseable = false;
checkCardModalV3.overflow = false;
checkCardModalV3.allLevel = 0;
checkCardModalV3.mustSelectList = [];
checkCardModalV3.selectAbleList = [];
// 下面就是resetCheckCardModalV3的内容
// modalState.isOpen = false;
// modalState.overflow = false;
// modalState.allLevel = 0;
// modalState.responseable = undefined;
// modalState.mustSelectList = [];
// modalState.selectAbleList = [];
};
return (
......
......@@ -11,14 +11,31 @@ import { store } from "@/store";
import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { checkCounterModal } = messageStore;
const NeosConfig = useConfig();
export const CheckCounterModal = () => {
const snapCheckCounterModal = useSnapshot(checkCounterModal);
const snapMat = useSnapshot(matStore);
const dispatch = store.dispatch;
const state = useAppSelector(selectCheckCounterModal);
const isOpen = state.isOpen;
const counterName = fetchStrings("!counter", `0x${state.counterType!}`);
const min = state.min || 0;
const options = state.options;
// const state = useAppSelector(selectCheckCounterModal);
// const isOpen = state.isOpen;
// const counterName = fetchStrings("!counter", `0x${state.counterType!}`);
// const min = state.min || 0;
// const options = state.options;
const isOpen = snapCheckCounterModal.isOpen;
const min = snapCheckCounterModal.min || 0;
const options = snapCheckCounterModal.options;
const counterName = fetchStrings(
"!counter",
`0x${snapCheckCounterModal.counterType!}`
);
const [selected, setSelected] = useState(new Array(options.length));
const sum = selected.reduce((sum, current) => sum + current, 0);
const finishable = sum == min;
......
......@@ -10,9 +10,13 @@ import { selectCurrentPhase } from "@/reducers/duel/phaseSlice";
import MsgWin = ygopro.StocGameMessage.MsgWin;
import { useConfig } from "@/config";
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig();
export const HintNotification = () => {
const hint = useAppSelector(selectHint);
// const hint = useAppSelector(selectHint);
const hint = useSnapshot(matStore.hint);
const currentPhase = useAppSelector(selectCurrentPhase);
const waiting = useAppSelector(selectWaiting);
const result = useAppSelector(selectDuelResult);
......
......@@ -12,11 +12,21 @@ import {
import { store } from "@/store";
import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { optionModal } = messageStore;
export const OptionModal = () => {
const dispatch = store.dispatch;
const isOpen = useAppSelector(selectOptionModalIsOpen);
const options = useAppSelector(selectOptionModalOptions);
// const isOpen = useAppSelector(selectOptionModalIsOpen);
// const options = useAppSelector(selectOptionModalOptions);
const snapOptionModal = useSnapshot(optionModal);
const isOpen = snapOptionModal.isOpen;
const options = snapOptionModal.options;
const [selected, setSelected] = useState<number | undefined>(undefined);
return (
......@@ -32,6 +42,8 @@ export const OptionModal = () => {
sendSelectOptionResponse(selected);
dispatch(setOptionModalIsOpen(false));
dispatch(resetOptionModal());
optionModal.isOpen = false;
optionModal.options = [];
}
}}
>
......
......@@ -26,6 +26,13 @@ import {
} from "@/reducers/duel/phaseSlice";
import { store } from "@/store";
import {
messageStore,
matStore,
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities,
} from "@/valtioStores";
import { useSnapshot } from "valtio";
const IconSize = "150%";
const SpaceSize = 16;
......@@ -47,12 +54,21 @@ const PhaseButton = (props: {
);
};
const { phase } = matStore;
export const Phase = () => {
const dispatch = store.dispatch;
const enableBp = useAppSelector(selectEnableBp);
const enableM2 = useAppSelector(selectEnableM2);
const enableEp = useAppSelector(selectEnableEp);
const currentPhase = useAppSelector(selectCurrentPhase);
// const enableBp = useAppSelector(selectEnableBp);
// const enableM2 = useAppSelector(selectEnableM2);
// const enableEp = useAppSelector(selectEnableEp);
// const currentPhase = useAppSelector(selectCurrentPhase);
const snapPhase = useSnapshot(phase);
const enableBp = snapPhase.enableBp;
const enableM2 = snapPhase.enableM2;
const enableEp = snapPhase.enableEp;
const currentPhase = snapPhase.currentPhase;
const [modalOpen, setModalOpen] = useState(false);
const response =
......@@ -69,7 +85,10 @@ export const Phase = () => {
dispatch(clearAllIdleInteractivities(0));
sendSelectIdleCmdResponse(6);
dispatch(setEnableBp(false));
// dispatch(setEnableBp(false));
FIXME_clearAllIdleInteractivities(0); // 为什么要clear两次?
FIXME_clearAllIdleInteractivities(0);
phase.enableBp = false;
};
const onM2 = () => {
dispatch(clearAllIdleInteractivities(0));
......@@ -77,6 +96,9 @@ export const Phase = () => {
sendSelectBattleCmdResponse(2);
dispatch(setEnableM2(false));
FIXME_clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(0);
phase.enableM2 = false;
};
const onEp = () => {
dispatch(clearAllIdleInteractivities(0));
......@@ -84,6 +106,9 @@ export const Phase = () => {
sendSelectIdleCmdResponse(response);
dispatch(setEnableEp(false));
FIXME_clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(0);
phase.enableEp = false;
};
const onSurrender = () => {
setModalOpen(true);
......
......@@ -17,10 +17,19 @@ import { store } from "@/store";
import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { positionModal } = messageStore;
export const PositionModal = () => {
const dispatch = store.dispatch;
const isOpen = useAppSelector(selectPositionModalIsOpen);
const positions = useAppSelector(selectPositionModalPositions);
const snapPositionModal = useSnapshot(positionModal);
// const isOpen = useAppSelector(selectPositionModalIsOpen);
// const positions = useAppSelector(selectPositionModalPositions);
const isOpen = snapPositionModal.isOpen;
const positions = snapPositionModal.positions;
const [selected, setSelected] = useState<ygopro.CardPosition | undefined>(
undefined
);
......@@ -38,6 +47,8 @@ export const PositionModal = () => {
sendSelectPositionResponse(selected);
dispatch(setPositionModalIsOpen(false));
dispatch(resetPositionModal());
positionModal.isOpen = false;
positionModal.positions = [];
}
}}
>
......
......@@ -26,13 +26,22 @@ import { resetSortCardModal } from "@/reducers/duel/mod";
import { selectSortCardModal } from "@/reducers/duel/modal/sortCardModalSlice";
import { store } from "@/store";
import { messageStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig();
const { sortCardModal } = messageStore;
export const SortCardModal = () => {
const dispatch = store.dispatch;
const state = useAppSelector(selectSortCardModal);
const isOpen = state.isOpen;
const options = state.options;
const snapSortCardModal = useSnapshot(sortCardModal);
// const state = useAppSelector(selectSortCardModal);
// const isOpen = state.isOpen;
// const options = state.options;
const isOpen = snapSortCardModal.isOpen;
const options = snapSortCardModal.options;
const [items, setItems] = useState(options);
const sensors = useSensors(
useSensor(PointerSensor),
......@@ -44,6 +53,8 @@ export const SortCardModal = () => {
const onFinish = () => {
sendSortCardResponse(items.map((item) => item.response));
dispatch(resetSortCardModal());
sortCardModal.isOpen = false;
sortCardModal.options = [];
};
const onDragEnd = (event: DragEndEvent) => {
const { active, over } = event;
......@@ -52,7 +63,7 @@ export const SortCardModal = () => {
setItems((items) => {
const oldIndex = items.findIndex((item) => item.response == active.id);
const newIndex = items.findIndex((item) => item.response === over?.id);
// @ts-ignore
return arrayMove(items, oldIndex, newIndex);
});
}
......
......@@ -18,10 +18,17 @@ const avatarSize = 40;
const ME_VALUE = "myself";
const OP_VALUE = "opponent";
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
export const PlayerStatus = () => {
const meInfo = useAppSelector(selectMeInitInfo);
const opInfo = useAppSelector(selectOpInitInfo);
const waiting = useAppSelector(selectWaiting) || false;
// const meInfo = useAppSelector(selectMeInitInfo);
// const opInfo = useAppSelector(selectOpInitInfo);
// const waiting = useAppSelector(selectWaiting) || false;
const meInfo = useSnapshot(matStore.initInfo.me);
const opInfo = useSnapshot(matStore.initInfo.op);
const waiting = useSnapshot(matStore).waiting;
return (
<CheckCard.Group
......
......@@ -9,12 +9,12 @@ import { chatStore } from "@/valtioStores";
export const DuelTimeLine = () => {
const [items, setItems] = useState<TimelineItemProps[]>([]);
const chat = useAppSelector(selectChat);
// const chat = useAppSelector(selectChat);
const stateChat = chatStore;
const snapChat = useSnapshot(stateChat);
// const chat = snapChat.message;
const chat = snapChat.message;
useEffect(() => {
setItems((prev) =>
......
......@@ -13,11 +13,22 @@ import { store } from "@/store";
import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { yesNoModal } = messageStore;
export const YesNoModal = () => {
const dispatch = store.dispatch;
const isOpen = useAppSelector(selectYesNoModalIsOpen);
const msg = useAppSelector(selectYesNOModalMsg);
const hint = useAppSelector(selectHint);
// const isOpen = useAppSelector(selectYesNoModalIsOpen);
// const msg = useAppSelector(selectYesNOModalMsg);
// const hint = useAppSelector(selectHint);
const snapYesNoModal = useSnapshot(yesNoModal);
const isOpen = snapYesNoModal.isOpen;
const msg = snapYesNoModal.msg;
const hint = useSnapshot(matStore.hint);
const preHintMsg = hint?.esHint || "";
return (
......@@ -31,6 +42,7 @@ export const YesNoModal = () => {
onClick={() => {
sendSelectEffectYnResponse(true);
dispatch(setYesNoModalIsOpen(false));
yesNoModal.isOpen = false;
}}
>
Yes
......@@ -39,6 +51,7 @@ export const YesNoModal = () => {
onClick={() => {
sendSelectEffectYnResponse(false);
dispatch(setYesNoModalIsOpen(false));
yesNoModal.isOpen = false;
}}
>
No
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment