列車走行位置へのジャンプ機能をuseCurrentTrainへ移動
This commit is contained in:
@@ -42,7 +42,8 @@ export const EachTrainInfoCore = ({
|
|||||||
from,
|
from,
|
||||||
navigate,
|
navigate,
|
||||||
}) => {
|
}) => {
|
||||||
const { currentTrain } = useCurrentTrain();
|
const { currentTrain, getCurrentStationData, getPosition } =
|
||||||
|
useCurrentTrain();
|
||||||
const { originalStationList, stationList } = useStationList();
|
const { originalStationList, stationList } = useStationList();
|
||||||
const { allTrainDiagram: trainList, allCustomTrainData } =
|
const { allTrainDiagram: trainList, allCustomTrainData } =
|
||||||
useAllTrainDiagram();
|
useAllTrainDiagram();
|
||||||
@@ -50,13 +51,10 @@ export const EachTrainInfoCore = ({
|
|||||||
const [currentTrainData, setCurrentTrainData] = useState();
|
const [currentTrainData, setCurrentTrainData] = useState();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentTrain.length) return;
|
const stationData = getCurrentStationData(data.trainNum);
|
||||||
setCurrentTrainData(
|
if (stationData) {
|
||||||
checkDuplicateTrainData(
|
setCurrentTrainData(stationData);
|
||||||
currentTrain.filter((d) => d.num == data.trainNum),
|
}
|
||||||
stationList
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}, [currentTrain, data.trainNum]);
|
}, [currentTrain, data.trainNum]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -100,7 +98,7 @@ export const EachTrainInfoCore = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const stopStationList = trainData.map((i) => {
|
const stopStationList = trainData.map((i) => {
|
||||||
const [station, se, time] = i.split(",");
|
const [station, se, time] = i.split(",");
|
||||||
if(se == "通編") setHaveThrough(true);
|
if (se == "通編") setHaveThrough(true);
|
||||||
return stationList.map((a) => a.filter((d) => d.StationName == station));
|
return stationList.map((a) => a.filter((d) => d.StationName == station));
|
||||||
});
|
});
|
||||||
const allThroughStationList = stopStationList.map((i, index, array) => {
|
const allThroughStationList = stopStationList.map((i, index, array) => {
|
||||||
@@ -205,7 +203,10 @@ export const EachTrainInfoCore = ({
|
|||||||
setHeadStation([]);
|
setHeadStation([]);
|
||||||
setTailStation([]);
|
setTailStation([]);
|
||||||
if (!TD) {
|
if (!TD) {
|
||||||
const specialTrainActualIDs = searchSpecialTrain(data.trainNum, trainList);
|
const specialTrainActualIDs = searchSpecialTrain(
|
||||||
|
data.trainNum,
|
||||||
|
trainList
|
||||||
|
);
|
||||||
setTrueTrainID(specialTrainActualIDs || []);
|
setTrueTrainID(specialTrainActualIDs || []);
|
||||||
setTrainData([]);
|
setTrainData([]);
|
||||||
return;
|
return;
|
||||||
@@ -247,71 +248,8 @@ export const EachTrainInfoCore = ({
|
|||||||
}, [trainData, data]);
|
}, [trainData, data]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//currentTrainData.Pos = "鴨川~端岡"; //test
|
const position = getPosition(currentTrainData);
|
||||||
if (!currentTrainData) return;
|
if (position) setCurrentPosition(position);
|
||||||
if (!currentTrainData?.Pos) return;
|
|
||||||
if (currentTrainData?.Pos.match("~")) {
|
|
||||||
const pos = currentTrainData?.Pos.replace("(下り)", "")
|
|
||||||
.replace("(上り)", "")
|
|
||||||
.replace("(徳島線)", "")
|
|
||||||
.replace("(高徳線)", "")
|
|
||||||
.split("~");
|
|
||||||
const direction = parseInt(currentTrainData?.Direction) || 0;
|
|
||||||
if (pos[0] == "児島" && pos[1] == "宇多津") {
|
|
||||||
setCurrentPosition(["M12", "Y09"]);
|
|
||||||
return;
|
|
||||||
} else if (pos[1] == "児島" && pos[0] == "宇多津") {
|
|
||||||
setCurrentPosition(["Y09", "M12"]);
|
|
||||||
return;
|
|
||||||
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予白滝") {
|
|
||||||
setCurrentPosition(["S18", "S14"]);
|
|
||||||
return;
|
|
||||||
} else if (pos[0] == "伊予白滝" && pos[1] == "伊予若宮") {
|
|
||||||
setCurrentPosition(["S14", "S18"]);
|
|
||||||
return;
|
|
||||||
} else if (pos[0] == "伊予大洲" && pos[1] == "伊予若宮") {
|
|
||||||
setCurrentPosition(["U14", "U14"]);
|
|
||||||
return;
|
|
||||||
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予大洲") {
|
|
||||||
setCurrentPosition(["U14", "U14"]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const currentPosID = Object.keys(originalStationList).map((key) => {
|
|
||||||
let firstStation = false;
|
|
||||||
let firstStationID = "";
|
|
||||||
let secondStation = false;
|
|
||||||
let secondStationID = "";
|
|
||||||
originalStationList[key].forEach((station) => {
|
|
||||||
if (station.Station_JP === pos[0]) {
|
|
||||||
firstStation = true;
|
|
||||||
firstStationID = station.StationNumber;
|
|
||||||
}
|
|
||||||
if (station.Station_JP === pos[1]) {
|
|
||||||
secondStation = true;
|
|
||||||
secondStationID = station.StationNumber;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (firstStation && secondStation) {
|
|
||||||
return [firstStationID, secondStationID];
|
|
||||||
} else return false;
|
|
||||||
});
|
|
||||||
const currentPos = currentPosID.filter((d) => d != false)[0];
|
|
||||||
if (currentPos) {
|
|
||||||
setCurrentPosition(direction == 0 ? currentPos.reverse() : currentPos);
|
|
||||||
} else if (direction == 0) {
|
|
||||||
setCurrentPosition([
|
|
||||||
getStationID(pos[1], stationList),
|
|
||||||
getStationID(pos[0], stationList),
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
setCurrentPosition([
|
|
||||||
getStationID(pos[0], stationList),
|
|
||||||
getStationID(pos[1], stationList),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setCurrentPosition([getStationID(currentTrainData?.Pos, stationList)]);
|
|
||||||
}
|
|
||||||
}, [currentTrainData]);
|
}, [currentTrainData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -393,7 +331,12 @@ export const EachTrainInfoCore = ({
|
|||||||
containerProps={{
|
containerProps={{
|
||||||
style: {
|
style: {
|
||||||
maxHeight: isLandscape ? height - 94 : (height / 100) * 70,
|
maxHeight: isLandscape ? height - 94 : (height / 100) * 70,
|
||||||
backgroundColor:getTrainType(customTrainDataDetector(data.trainNum, allCustomTrainData).type).data === "notService" ? "#777777ff" :"white"
|
backgroundColor:
|
||||||
|
getTrainType(
|
||||||
|
customTrainDataDetector(data.trainNum, allCustomTrainData).type
|
||||||
|
).data === "notService"
|
||||||
|
? "#777777ff"
|
||||||
|
: "white",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
shortHeader={
|
shortHeader={
|
||||||
@@ -424,7 +367,13 @@ export const EachTrainInfoCore = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{getTrainType(customTrainDataDetector(data.trainNum, allCustomTrainData).type).data === "notService" &&<Text style={{backgroundColor:"#ffffffc2",fontWeight:"bold"}}>この列車には乗車できません。</Text>}
|
{getTrainType(
|
||||||
|
customTrainDataDetector(data.trainNum, allCustomTrainData).type
|
||||||
|
).data === "notService" && (
|
||||||
|
<Text style={{ backgroundColor: "#ffffffc2", fontWeight: "bold" }}>
|
||||||
|
この列車には乗車できません。
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
{headStation.length != 0 &&
|
{headStation.length != 0 &&
|
||||||
headStation.map((i, index) =>
|
headStation.map((i, index) =>
|
||||||
showHeadStation.findIndex((d) => d == index) == -1 ? (
|
showHeadStation.findIndex((d) => d == index) == -1 ? (
|
||||||
@@ -473,10 +422,11 @@ export const EachTrainInfoCore = ({
|
|||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
margin: 10,
|
margin: 10,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
alignItems: "center", backgroundColor:"#ffffffc2"
|
alignItems: "center",
|
||||||
|
backgroundColor: "#ffffffc2",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={{ fontSize: 18, fontWeight: "bold", color: "black",}}>
|
<Text style={{ fontSize: 18, fontWeight: "bold", color: "black" }}>
|
||||||
Twitterで検索
|
Twitterで検索
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@@ -494,12 +444,14 @@ export const EachTrainInfoCore = ({
|
|||||||
currentTrainData,
|
currentTrainData,
|
||||||
openStationACFromEachTrainInfo,
|
openStationACFromEachTrainInfo,
|
||||||
showThrew,
|
showThrew,
|
||||||
key: i + "-stop"
|
|
||||||
}}
|
}}
|
||||||
|
key={i + "-stop"}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
<Text style={{backgroundColor:"#ffffffc2"}}>時刻が斜体,青色になっている時刻はコミュニティで追加されている独自データです。</Text>
|
<Text style={{ backgroundColor: "#ffffffc2" }}>
|
||||||
|
時刻が斜体,青色になっている時刻はコミュニティで追加されている独自データです。
|
||||||
|
</Text>
|
||||||
{tailStation.length != 0 &&
|
{tailStation.length != 0 &&
|
||||||
tailStation.map(({ station, dia }, index) =>
|
tailStation.map(({ station, dia }, index) =>
|
||||||
showTailStation.findIndex((d) => d == index) == -1 ? (
|
showTailStation.findIndex((d) => d == index) == -1 ? (
|
||||||
@@ -540,7 +492,7 @@ export const EachTrainInfoCore = ({
|
|||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
borderBottomColor: "#f0f0f0",
|
borderBottomColor: "#f0f0f0",
|
||||||
backgroundColor:"#ffffffc2",
|
backgroundColor: "#ffffffc2",
|
||||||
flex: 1,
|
flex: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { TouchableOpacity, View, Text, Linking } from "react-native";
|
import { TouchableOpacity, View, Text, Linking } from "react-native";
|
||||||
import { useStationList } from "@/stateBox/useStationList";
|
|
||||||
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
|
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
|
||||||
import AntDesign from "react-native-vector-icons/AntDesign";
|
import AntDesign from "react-native-vector-icons/AntDesign";
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -10,10 +9,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
export const StationTrainPositionButton: FC<Props> = (props) => {
|
export const StationTrainPositionButton: FC<Props> = (props) => {
|
||||||
const { stationNumber, onExit, navigate } = props;
|
const { stationNumber, onExit, navigate } = props;
|
||||||
const {
|
const { setInjectData } = useCurrentTrain();
|
||||||
inject,
|
|
||||||
} = useCurrentTrain();
|
|
||||||
const { getInjectJavascriptAddress } = useStationList();
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={{
|
style={{
|
||||||
@@ -23,12 +19,16 @@ export const StationTrainPositionButton: FC<Props> = (props) => {
|
|||||||
alignContent: "center",
|
alignContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
margin: 2,
|
margin: 2,
|
||||||
flex: 1
|
flex: 1,
|
||||||
|
}}
|
||||||
|
onLongPress={() => {
|
||||||
|
navigate("positions", { screen: "Apps" });
|
||||||
|
setInjectData({ type: "station", stationNumber, fixed: true });
|
||||||
|
onExit();
|
||||||
}}
|
}}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
navigate("positions", { screen: "Apps" });
|
navigate("positions", { screen: "Apps" });
|
||||||
const script = getInjectJavascriptAddress(stationNumber);
|
setInjectData({ type: "station", stationNumber, fixed: false });
|
||||||
inject(script);
|
|
||||||
onExit();
|
onExit();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@@ -23,7 +23,8 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => {
|
|||||||
const { navigate } = useNavigation();
|
const { navigate } = useNavigation();
|
||||||
const { favoriteStation } = useFavoriteStation();
|
const { favoriteStation } = useFavoriteStation();
|
||||||
const { isLandscape } = useDeviceOrientationChange();
|
const { isLandscape } = useDeviceOrientationChange();
|
||||||
const { originalStationList, stationList, getInjectJavascriptAddress } = useStationList();
|
const { originalStationList, stationList, getInjectJavascriptAddress } =
|
||||||
|
useStationList();
|
||||||
const {
|
const {
|
||||||
setSelectedLine,
|
setSelectedLine,
|
||||||
mapsStationData: stationData,
|
mapsStationData: stationData,
|
||||||
@@ -51,7 +52,6 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMessage = (event) => {
|
const onMessage = (event) => {
|
||||||
const { data } = event.nativeEvent;
|
const { data } = event.nativeEvent;
|
||||||
/**
|
/**
|
||||||
@@ -137,7 +137,9 @@ export const AppsWebView = ({ openStationACFromEachTrainInfo }) => {
|
|||||||
if (!stationData) return () => {};
|
if (!stationData) return () => {};
|
||||||
if (!originalStationList) return () => {};
|
if (!originalStationList) return () => {};
|
||||||
if (favoriteStation.length < 1) return () => {};
|
if (favoriteStation.length < 1) return () => {};
|
||||||
const string = getInjectJavascriptAddress(favoriteStation[0][0].StationNumber);
|
const string = getInjectJavascriptAddress(
|
||||||
|
favoriteStation[0][0].StationNumber
|
||||||
|
);
|
||||||
if (!string) return () => {};
|
if (!string) return () => {};
|
||||||
webview?.current.injectJavaScript(string);
|
webview?.current.injectJavaScript(string);
|
||||||
once = true;
|
once = true;
|
||||||
|
@@ -8,6 +8,9 @@ import React, {
|
|||||||
import { HeaderConfig } from "../lib/HeaderConfig";
|
import { HeaderConfig } from "../lib/HeaderConfig";
|
||||||
|
|
||||||
import useInterval from "../lib/useInterval";
|
import useInterval from "../lib/useInterval";
|
||||||
|
import { useStationList } from "./useStationList";
|
||||||
|
import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData";
|
||||||
|
import { getStationID } from "@/lib/eachTrainInfoCoreLib/getStationData";
|
||||||
const initialState = {
|
const initialState = {
|
||||||
webview: {},
|
webview: {},
|
||||||
currentTrain: [],
|
currentTrain: [],
|
||||||
@@ -16,6 +19,11 @@ const initialState = {
|
|||||||
setCurrentTrainLoading: () => {},
|
setCurrentTrainLoading: () => {},
|
||||||
getCurrentTrain: () => {},
|
getCurrentTrain: () => {},
|
||||||
inject: (i) => {},
|
inject: (i) => {},
|
||||||
|
fixedPosition: null,
|
||||||
|
setFixedPosition: () => {},
|
||||||
|
setInjectData: (e) => {},
|
||||||
|
getCurrentStationData: (e) => {},
|
||||||
|
getPosition: (e) => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const CurrentTrainContext = createContext(initialState);
|
const CurrentTrainContext = createContext(initialState);
|
||||||
@@ -27,6 +35,111 @@ export const useCurrentTrain = () => {
|
|||||||
export const CurrentTrainProvider = ({ children }) => {
|
export const CurrentTrainProvider = ({ children }) => {
|
||||||
const [currentTrain, setCurrentTrain] = useState([]); //現在在線中の全列車 { num: 列車番号, delay: 遅延時分(状態), Pos: 位置情報 }
|
const [currentTrain, setCurrentTrain] = useState([]); //現在在線中の全列車 { num: 列車番号, delay: 遅延時分(状態), Pos: 位置情報 }
|
||||||
const [currentTrainLoading, setCurrentTrainLoading] = useState("loading"); // success, error, loading
|
const [currentTrainLoading, setCurrentTrainLoading] = useState("loading"); // success, error, loading
|
||||||
|
|
||||||
|
const { getInjectJavascriptAddress, stationList, originalStationList } =
|
||||||
|
useStationList();
|
||||||
|
|
||||||
|
const [fixedPosition, setFixedPosition] = useState(null);
|
||||||
|
const [_, setIntervalState] = useInterval(
|
||||||
|
() => {
|
||||||
|
if (!webview.current) return;
|
||||||
|
inject(fixedPosition);
|
||||||
|
},
|
||||||
|
60000,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
if (fixedPosition) {
|
||||||
|
setIntervalState.start();
|
||||||
|
} else {
|
||||||
|
setIntervalState.stop();
|
||||||
|
}
|
||||||
|
}, [fixedPosition]);
|
||||||
|
const getPosition = (currentTrainData) => {
|
||||||
|
console.log(currentTrainData);
|
||||||
|
//currentTrainData.Pos = "鴨川~端岡"; //test
|
||||||
|
if (!currentTrainData) return;
|
||||||
|
if (!currentTrainData?.Pos) return;
|
||||||
|
if (currentTrainData?.Pos.match("~")) {
|
||||||
|
const pos = currentTrainData?.Pos.replace("(下り)", "")
|
||||||
|
.replace("(上り)", "")
|
||||||
|
.replace("(徳島線)", "")
|
||||||
|
.replace("(高徳線)", "")
|
||||||
|
.split("~");
|
||||||
|
const direction = parseInt(currentTrainData?.Direction) || 0;
|
||||||
|
if (pos[0] == "児島" && pos[1] == "宇多津") {
|
||||||
|
return ["M12", "Y09"];
|
||||||
|
} else if (pos[1] == "児島" && pos[0] == "宇多津") {
|
||||||
|
return ["Y09", "M12"];
|
||||||
|
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予白滝") {
|
||||||
|
return ["S18", "S14"];
|
||||||
|
} else if (pos[0] == "伊予白滝" && pos[1] == "伊予若宮") {
|
||||||
|
return ["S14", "S18"];
|
||||||
|
} else if (pos[0] == "伊予大洲" && pos[1] == "伊予若宮") {
|
||||||
|
return ["U14", "U14"];
|
||||||
|
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予大洲") {
|
||||||
|
return ["U14", "U14"];
|
||||||
|
}
|
||||||
|
const currentPosID = Object.keys(originalStationList).map((key) => {
|
||||||
|
let firstStation = false;
|
||||||
|
let firstStationID = "";
|
||||||
|
let secondStation = false;
|
||||||
|
let secondStationID = "";
|
||||||
|
originalStationList[key].forEach((station) => {
|
||||||
|
if (station.Station_JP === pos[0]) {
|
||||||
|
firstStation = true;
|
||||||
|
firstStationID = station.StationNumber;
|
||||||
|
}
|
||||||
|
if (station.Station_JP === pos[1]) {
|
||||||
|
secondStation = true;
|
||||||
|
secondStationID = station.StationNumber;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (firstStation && secondStation) {
|
||||||
|
return [firstStationID, secondStationID];
|
||||||
|
} else return false;
|
||||||
|
});
|
||||||
|
const currentPos = currentPosID.filter((d) => d != false)[0];
|
||||||
|
if (currentPos) {
|
||||||
|
return direction == 0 ? currentPos.reverse() : currentPos;
|
||||||
|
} else if (direction == 0) {
|
||||||
|
return [
|
||||||
|
getStationID(pos[1], stationList),
|
||||||
|
getStationID(pos[0], stationList),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
getStationID(pos[0], stationList),
|
||||||
|
getStationID(pos[1], stationList),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return [getStationID(currentTrainData?.Pos, stationList)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const setInjectData = ({ type, number, fixed }) => {
|
||||||
|
if (type === "station") {
|
||||||
|
const script = getInjectJavascriptAddress(number);
|
||||||
|
inject(script);
|
||||||
|
if (fixed) {
|
||||||
|
setFixedPosition(script);
|
||||||
|
}
|
||||||
|
} else if (type === "station") {
|
||||||
|
const script = getInjectJavascriptAddress(number);
|
||||||
|
inject(script);
|
||||||
|
if (fixed) {
|
||||||
|
setFixedPosition(script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getCurrentStationData = (e) => {
|
||||||
|
//e:trainNumber
|
||||||
|
if (!currentTrain.length) return;
|
||||||
|
return checkDuplicateTrainData(
|
||||||
|
currentTrain.filter((d) => d.num == e),
|
||||||
|
stationList
|
||||||
|
);
|
||||||
|
};
|
||||||
const getCurrentTrain = () => {
|
const getCurrentTrain = () => {
|
||||||
fetch("https://n8n.haruk.in/webhook/c501550c-7d1b-4e50-927b-4429fe18931a")
|
fetch("https://n8n.haruk.in/webhook/c501550c-7d1b-4e50-927b-4429fe18931a")
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
@@ -88,6 +201,9 @@ export const CurrentTrainProvider = ({ children }) => {
|
|||||||
setCurrentTrainLoading,
|
setCurrentTrainLoading,
|
||||||
getCurrentTrain,
|
getCurrentTrain,
|
||||||
inject,
|
inject,
|
||||||
|
setInjectData,
|
||||||
|
getCurrentStationData,
|
||||||
|
getPosition,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
Reference in New Issue
Block a user