fix: update preview-page bug fix sights

This commit is contained in:
2025-11-26 19:37:26 +03:00
parent aaeaed3fa5
commit 11133b6839
4 changed files with 111 additions and 30 deletions

View File

@@ -1,17 +1,12 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { flushSync } from "react-dom"; import { flushSync } from "react-dom";
import type { PointerEvent as ReactPointerEvent } from "react"; import type { PointerEvent as ReactPointerEvent, CSSProperties } from "react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { useMapData } from "../MapDataContext"; import { useMapData } from "../MapDataContext";
import { useTransform } from "../TransformContext"; import { useTransform } from "../TransformContext";
import { coordinatesToLocal, localToCoordinates } from "../utils"; import { coordinatesToLocal, localToCoordinates } from "../utils";
import { import { BACKGROUND_COLOR, SCALE_FACTOR, UP_SCALE } from "../Constants";
BACKGROUND_COLOR,
PATH_COLOR,
SCALE_FACTOR,
UP_SCALE,
} from "../Constants";
import { languageStore } from "@shared"; import { languageStore } from "@shared";
import { SightData } from "../types"; import { SightData } from "../types";
@@ -360,7 +355,8 @@ const computeViewTransform = (
}; };
const backgroundColor = toColor(BACKGROUND_COLOR); const backgroundColor = toColor(BACKGROUND_COLOR);
const pathColor = toColor(PATH_COLOR); // Override route & station color to ED1C24
const pathColor = toColor(0xed1c24);
export const WebGLRouteMapPrototype = observer(() => { export const WebGLRouteMapPrototype = observer(() => {
const { const {
@@ -370,6 +366,7 @@ export const WebGLRouteMapPrototype = observer(() => {
sightData, sightData,
setSelectedSight, setSelectedSight,
setStationOffset, setStationOffset,
setStationAlign,
setSightCoordinates, setSightCoordinates,
setMapCenter, setMapCenter,
} = useMapData(); } = useMapData();
@@ -440,6 +437,11 @@ export const WebGLRouteMapPrototype = observer(() => {
const [liveSightPositions, setLiveSightPositions] = useState< const [liveSightPositions, setLiveSightPositions] = useState<
Map<number, SightLivePosition> Map<number, SightLivePosition>
>(new Map()); >(new Map());
type StationAlignment = "left" | "center" | "right";
const [stationAlignments, setStationAlignments] = useState<
Map<number, StationAlignment>
>(new Map());
const [hoveredStationId, setHoveredStationId] = useState<number | null>(null);
const lastCenterRef = useRef<{ const lastCenterRef = useRef<{
latitude: number | null; latitude: number | null;
longitude: number | null; longitude: number | null;
@@ -586,6 +588,45 @@ export const WebGLRouteMapPrototype = observer(() => {
}, 120); }, 120);
}, [cancelScheduledCenterCommit, commitCenter]); }, [cancelScheduledCenterCommit, commitCenter]);
useEffect(() => {
if (hoveredStationId == null) {
return;
}
const handleKeyDown = (event: KeyboardEvent) => {
const key = event.key;
let nextAlignment: StationAlignment | null = null;
let alignNumber: number | null = null;
if (key === "1") {
nextAlignment = "left";
alignNumber = 1;
} else if (key === "2") {
nextAlignment = "center";
alignNumber = 2;
} else if (key === "3") {
nextAlignment = "right";
alignNumber = 3;
}
if (!nextAlignment || alignNumber === null) {
return;
}
setStationAlignments((prev) => {
const next = new Map(prev);
next.set(hoveredStationId, nextAlignment as StationAlignment);
return next;
});
setStationAlign(hoveredStationId, alignNumber);
};
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [hoveredStationId, setStationAlignments, setStationAlign]);
useEffect(() => { useEffect(() => {
return () => { return () => {
cancelScheduledCenterCommit(); cancelScheduledCenterCommit();
@@ -1138,8 +1179,8 @@ export const WebGLRouteMapPrototype = observer(() => {
const { scale, translation } = transform; const { scale, translation } = transform;
const desiredRouteWidthCss = 13; const desiredRouteWidthCss = 7;
const desiredStationDiameterCss = 30; const desiredStationDiameterCss = 12;
const pointOuterSizePx = desiredStationDiameterCss * dpr; const pointOuterSizePx = desiredStationDiameterCss * dpr;
const pointInnerSizePx = pointOuterSizePx * 0.8; const pointInnerSizePx = pointOuterSizePx * 0.8;
@@ -1763,9 +1804,32 @@ export const WebGLRouteMapPrototype = observer(() => {
const secondaryFontSize = 13 * fontScale; const secondaryFontSize = 13 * fontScale;
const secondaryMarginTop = 5 * fontScale; const secondaryMarginTop = 5 * fontScale;
const backendAlign = station.align;
const alignmentFromData: StationAlignment =
backendAlign === 1
? "left"
: backendAlign === 3
? "right"
: "center";
const alignment: StationAlignment =
stationAlignments.get(station.id) ?? alignmentFromData;
const secondaryPositionStyle: CSSProperties =
alignment === "left"
? { left: 0, transform: "none" }
: alignment === "right"
? { right: 0, transform: "none" }
: { left: "50%", transform: "translateX(-50%)" };
return ( return (
<div <div
key={station.id} key={station.id}
onMouseEnter={() => setHoveredStationId(station.id)}
onMouseLeave={() =>
setHoveredStationId((prev) =>
prev === station.id ? null : prev
)
}
onPointerDown={(event) => onPointerDown={(event) =>
handleStationPointerDown( handleStationPointerDown(
event, event,
@@ -1807,28 +1871,40 @@ export const WebGLRouteMapPrototype = observer(() => {
> >
<div <div
style={{ style={{
fontWeight: 700, position: "relative",
fontSize: primaryFontSize, display: "inline-block",
textShadow: "0 0 4px rgba(0,0,0,0.6)",
pointerEvents: "none", pointerEvents: "none",
}} }}
> >
{station.name}
</div>
{showSecondary ? (
<div <div
style={{ style={{
fontWeight: 400, fontWeight: 700,
marginTop: -1 * secondaryMarginTop, fontSize: primaryFontSize,
fontSize: secondaryFontSize, textShadow: "0 0 4px rgba(0,0,0,0.6)",
color: "#CBCBCB",
textShadow: "0 0 3px rgba(0,0,0,0.4)",
pointerEvents: "none", pointerEvents: "none",
}} }}
> >
{translatedStation?.name} {station.name}
</div> </div>
) : null} {showSecondary ? (
<div
style={{
position: "absolute",
top: "100%",
marginTop: -1 * secondaryMarginTop,
fontWeight: 400,
fontSize: secondaryFontSize,
color: "#CBCBCB",
textShadow: "0 0 3px rgba(0,0,0,0.4)",
whiteSpace: "nowrap",
...secondaryPositionStyle,
pointerEvents: "none",
}}
>
{translatedStation?.name}
</div>
) : null}
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -505,7 +505,12 @@ const LinkedStationsContentsInner = <
}} }}
renderOption={(props, option) => ( renderOption={(props, option) => (
<li {...props} key={option.id}> <li {...props} key={option.id}>
{String(option.name)} <div className="flex justify-between items-center w-full">
<p>{String(option.name)}</p>
<p className="text-xs text-gray-500 max-w-[300px] mr-4 truncate">
{String(option.description)}
</p>
</div>
</li> </li>
)} )}
/> />

View File

@@ -51,8 +51,8 @@ export const StationListPage = observer(() => {
}, },
}, },
{ {
field: "system_name", field: "description",
headerName: "Системное название", headerName: "Описание",
flex: 1, flex: 1,
renderCell: (params: GridRenderCellParams) => { renderCell: (params: GridRenderCellParams) => {
return ( return (
@@ -130,7 +130,7 @@ export const StationListPage = observer(() => {
const rows = filteredStations().map((station: any) => ({ const rows = filteredStations().map((station: any) => ({
id: station.id, id: station.id,
name: station.name, name: station.name,
system_name: station.system_name, description: station.description,
direction: station.direction, direction: station.direction,
})); }));

View File

@@ -10,6 +10,7 @@ import {
import { import {
BackButton, BackButton,
createSightStore, createSightStore,
editSightStore,
languageStore, languageStore,
SelectArticleModal, SelectArticleModal,
TabPanel, TabPanel,
@@ -51,9 +52,6 @@ export const CreateRightTab = observer(
unlinkPreviewMedia, unlinkPreviewMedia,
createLinkWithRightArticle, createLinkWithRightArticle,
deleteRightArticleMedia, deleteRightArticleMedia,
setFileToUpload,
setUploadMediaOpen,
uploadMediaOpen,
unlinkRightAritcle, unlinkRightAritcle,
deleteRightArticle, deleteRightArticle,
linkExistingRightArticle, linkExistingRightArticle,
@@ -62,6 +60,8 @@ export const CreateRightTab = observer(
updateRightArticles, updateRightArticles,
} = createSightStore; } = createSightStore;
const { language } = languageStore; const { language } = languageStore;
const { setFileToUpload, setUploadMediaOpen, uploadMediaOpen } =
editSightStore;
const [selectArticleDialogOpen, setSelectArticleDialogOpen] = const [selectArticleDialogOpen, setSelectArticleDialogOpen] =
useState(false); useState(false);