mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2025-12-25 15:39:35 -05:00
added tooltip in explaining how to reroute connectors
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Box, IconButton, Paper, Typography, Fade } from '@mui/material';
|
||||
import { Close as CloseIcon } from '@mui/icons-material';
|
||||
import { useUiStateStore } from 'src/stores/uiStateStore';
|
||||
import { useScene } from 'src/hooks/useScene';
|
||||
import { useTranslation } from 'src/stores/localeStore';
|
||||
|
||||
const STORAGE_KEY = 'fossflow_connector_reroute_hint_dismissed';
|
||||
|
||||
export const ConnectorRerouteTooltip = () => {
|
||||
const { t } = useTranslation('connectorRerouteTooltip');
|
||||
const [showTooltip, setShowTooltip] = useState(false);
|
||||
const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 });
|
||||
const mode = useUiStateStore((state) => state.mode);
|
||||
const mouse = useUiStateStore((state) => state.mouse);
|
||||
const { connectors } = useScene();
|
||||
const previousModeRef = useRef(mode);
|
||||
const shownForConnectorRef = useRef<string | null>(null);
|
||||
const [isDismissed, setIsDismissed] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
// Check if the hint has been dismissed before
|
||||
const dismissed = localStorage.getItem(STORAGE_KEY);
|
||||
if (dismissed !== 'true') {
|
||||
setIsDismissed(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDismissed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const previousMode = previousModeRef.current;
|
||||
|
||||
// Detect when we transition from isConnecting to not isConnecting (connection completed)
|
||||
if (
|
||||
mode.type === 'CONNECTOR' &&
|
||||
previousMode.type === 'CONNECTOR' &&
|
||||
previousMode.isConnecting &&
|
||||
!mode.isConnecting &&
|
||||
!mode.id // After connection is complete, id is set to null
|
||||
) {
|
||||
// Find the most recently created connector
|
||||
const latestConnector = connectors[connectors.length - 1];
|
||||
|
||||
if (latestConnector && latestConnector.id !== shownForConnectorRef.current) {
|
||||
// Show tooltip near the mouse position
|
||||
setTooltipPosition({
|
||||
x: mouse.position.screen.x,
|
||||
y: mouse.position.screen.y
|
||||
});
|
||||
setShowTooltip(true);
|
||||
shownForConnectorRef.current = latestConnector.id;
|
||||
|
||||
// Auto-hide after 15 seconds
|
||||
const timer = setTimeout(() => {
|
||||
setShowTooltip(false);
|
||||
}, 15000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
|
||||
// Hide tooltip when switching away from connector mode
|
||||
if (mode.type !== 'CONNECTOR') {
|
||||
setShowTooltip(false);
|
||||
}
|
||||
|
||||
previousModeRef.current = mode;
|
||||
}, [mode, connectors, mouse.position.screen, isDismissed]);
|
||||
|
||||
const handleDismiss = () => {
|
||||
setShowTooltip(false);
|
||||
setIsDismissed(true);
|
||||
localStorage.setItem(STORAGE_KEY, 'true');
|
||||
};
|
||||
|
||||
if (!showTooltip || isDismissed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fade in={showTooltip} timeout={300}>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'fixed',
|
||||
left: Math.min(tooltipPosition.x + 20, window.innerWidth - 370),
|
||||
top: Math.min(tooltipPosition.y - 80, window.innerHeight - 120),
|
||||
zIndex: 1400, // Above most UI elements
|
||||
maxWidth: 340
|
||||
}}
|
||||
>
|
||||
<Paper
|
||||
elevation={4}
|
||||
sx={{
|
||||
p: 2,
|
||||
pr: 5,
|
||||
backgroundColor: 'background.paper',
|
||||
borderLeft: '4px solid',
|
||||
borderLeftColor: 'success.main'
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={handleDismiss}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
right: 4,
|
||||
top: 4
|
||||
}}
|
||||
>
|
||||
<CloseIcon fontSize="small" />
|
||||
</IconButton>
|
||||
|
||||
<Typography variant="subtitle2" gutterBottom sx={{ fontWeight: 600 }}>
|
||||
{t('title')}
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||
{t('instructionStart')}
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
<strong>{t('instructionSelect')}</strong> {t('instructionMiddle')} <strong>{t('instructionClick')}</strong> {t('instructionAnd')} <strong>{t('instructionDrag')}</strong> {t('instructionEnd')}
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Fade>
|
||||
);
|
||||
};
|
||||
@@ -20,6 +20,7 @@ import { HelpDialog } from '../HelpDialog/HelpDialog';
|
||||
import { SettingsDialog } from '../SettingsDialog/SettingsDialog';
|
||||
import { ConnectorHintTooltip } from '../ConnectorHintTooltip/ConnectorHintTooltip';
|
||||
import { ConnectorEmptySpaceTooltip } from '../ConnectorEmptySpaceTooltip/ConnectorEmptySpaceTooltip';
|
||||
import { ConnectorRerouteTooltip } from '../ConnectorRerouteTooltip/ConnectorRerouteTooltip';
|
||||
import { ImportHintTooltip } from '../ImportHintTooltip/ImportHintTooltip';
|
||||
import { LassoHintTooltip } from '../LassoHintTooltip/LassoHintTooltip';
|
||||
|
||||
@@ -249,6 +250,7 @@ export const UiOverlay = () => {
|
||||
{/* Show hint tooltips only in editable mode */}
|
||||
{editorMode === EditorModeEnum.EDITABLE && <ConnectorHintTooltip toolMenuRef={toolMenuRef} />}
|
||||
{editorMode === EditorModeEnum.EDITABLE && <ConnectorEmptySpaceTooltip />}
|
||||
{editorMode === EditorModeEnum.EDITABLE && <ConnectorRerouteTooltip />}
|
||||
{editorMode === EditorModeEnum.EDITABLE && <ImportHintTooltip />}
|
||||
{editorMode === EditorModeEnum.EDITABLE && <LassoHintTooltip toolMenuRef={toolMenuRef} />}
|
||||
|
||||
|
||||
@@ -100,6 +100,16 @@ const locale: LocaleProps = {
|
||||
instructionMiddle: "(☰) in the top left corner, then select",
|
||||
openButton: "\"Open\"",
|
||||
instructionEnd: "to load your diagram files."
|
||||
},
|
||||
connectorRerouteTooltip: {
|
||||
title: "Tip: Reroute Connectors",
|
||||
instructionStart: "Once your connectors are placed you can reroute them as you please.",
|
||||
instructionSelect: "Select the connector",
|
||||
instructionMiddle: "first, then",
|
||||
instructionClick: "click on the connector path",
|
||||
instructionAnd: "and",
|
||||
instructionDrag: "drag",
|
||||
instructionEnd: "to change it!"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -100,6 +100,16 @@ const locale: LocaleProps = {
|
||||
instructionMiddle: "(☰),然后选择",
|
||||
openButton: "\"打开\"",
|
||||
instructionEnd: "来加载您的图表文件。"
|
||||
},
|
||||
connectorRerouteTooltip: {
|
||||
title: "提示:重新规划连接器路径",
|
||||
instructionStart: "连接器放置后,您可以随意重新规划路径。",
|
||||
instructionSelect: "先选择连接器",
|
||||
instructionMiddle: ",然后",
|
||||
instructionClick: "点击连接器路径",
|
||||
instructionAnd: "并",
|
||||
instructionDrag: "拖拽",
|
||||
instructionEnd: "即可更改!"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -108,6 +108,16 @@ export interface LocaleProps {
|
||||
openButton: string;
|
||||
instructionEnd: string;
|
||||
};
|
||||
connectorRerouteTooltip: {
|
||||
title: string;
|
||||
instructionStart: string;
|
||||
instructionSelect: string;
|
||||
instructionMiddle: string;
|
||||
instructionClick: string;
|
||||
instructionAnd: string;
|
||||
instructionDrag: string;
|
||||
instructionEnd: string;
|
||||
};
|
||||
// other namespaces can be added here
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user