fix(Map): New windows systems

This commit is contained in:
achichenkov
2025-01-11 13:36:21 +03:00
parent e77a42dfda
commit b100052453
9 changed files with 161 additions and 62 deletions

View File

@@ -1,48 +1,11 @@
import 'react-grid-layout/css/styles.css'; import 'react-grid-layout/css/styles.css';
import 'react-resizable/css/styles.css'; import 'react-resizable/css/styles.css';
import { import { useMemo, useState } from 'react';
LocalCharacters,
RoutesWidget,
SystemInfo,
SystemSignatures,
} from '@/hooks/Mapper/components/mapInterface/widgets';
import { useState } from 'react';
import { SESSION_KEY } from '@/hooks/Mapper/constants.ts'; import { SESSION_KEY } from '@/hooks/Mapper/constants.ts';
import { WindowManager } from '@/hooks/Mapper/components/ui-kit/WindowManager'; import { WindowManager } from '@/hooks/Mapper/components/ui-kit/WindowManager';
import { WindowProps } from '@/hooks/Mapper/components/ui-kit/WindowManager/types.ts'; import { WindowProps } from '@/hooks/Mapper/components/ui-kit/WindowManager/types.ts';
import { CURRENT_WINDOWS_VERSION, DEFAULT_WIDGETS } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
const CURRENT_WINDOWS_VERSION = 2; import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
const DEFAULT: WindowProps[] = [
{
id: 'info',
position: { x: 10, y: 10 },
size: { width: 250, height: 200 },
zIndex: 0,
content: () => <SystemInfo />,
},
{
id: 'signatures',
position: { x: 10, y: 220 },
size: { width: 250, height: 300 },
zIndex: 0,
content: () => <SystemSignatures />,
},
{
id: 'local',
position: { x: 270, y: 10 },
size: { width: 250, height: 510 },
zIndex: 0,
content: () => <LocalCharacters />,
},
{
id: 'routes',
position: { x: 10, y: 530 },
size: { width: 510, height: 200 },
zIndex: 0,
content: () => <RoutesWidget />,
},
];
type WindowsLS = { type WindowsLS = {
windows: WindowProps[]; windows: WindowProps[];
@@ -60,19 +23,19 @@ const restoreWindowsFromLS = (): WindowProps[] => {
const raw = localStorage.getItem(SESSION_KEY.windows); const raw = localStorage.getItem(SESSION_KEY.windows);
if (!raw) { if (!raw) {
console.warn('No windows found in local storage!!'); console.warn('No windows found in local storage!!');
return DEFAULT; return DEFAULT_WIDGETS;
} }
const { version, windows } = JSON.parse(raw) as WindowsLS; const { version, windows } = JSON.parse(raw) as WindowsLS;
if (!version || CURRENT_WINDOWS_VERSION > version) { if (!version || CURRENT_WINDOWS_VERSION > version) {
return DEFAULT; return DEFAULT_WIDGETS;
} }
// eslint-disable-next-line no-debugger // eslint-disable-next-line no-debugger
const out = (windows as Omit<WindowProps, 'content'>[]) const out = (windows as Omit<WindowProps, 'content'>[])
.filter(x => DEFAULT.find(def => def.id === x.id)) .filter(x => DEFAULT_WIDGETS.find(def => def.id === x.id))
.map(x => { .map(x => {
const content = DEFAULT.find(def => def.id === x.id)?.content; const content = DEFAULT_WIDGETS.find(def => def.id === x.id)?.content;
return { ...x, content: content! }; return { ...x, content: content! };
}); });
@@ -81,10 +44,15 @@ const restoreWindowsFromLS = (): WindowProps[] => {
export const MapInterface = () => { export const MapInterface = () => {
const [items, setItems] = useState<WindowProps[]>(restoreWindowsFromLS); const [items, setItems] = useState<WindowProps[]>(restoreWindowsFromLS);
const { windowsVisible } = useMapRootState();
const itemsFiltered = useMemo(() => {
return items.filter(x => windowsVisible.some(j => x.id === j));
}, [items, windowsVisible]);
return ( return (
<WindowManager <WindowManager
windows={items} windows={itemsFiltered}
dragSelector=".react-grid-dragHandleExample" dragSelector=".react-grid-dragHandleExample"
onChange={x => { onChange={x => {
saveWindowsToLS(x); saveWindowsToLS(x);

View File

@@ -1,5 +1,4 @@
export * from './Widget'; export * from './Widget';
export * from './WidgetsGrid';
export * from './SystemSettingsDialog'; export * from './SystemSettingsDialog';
export * from './SystemCustomLabelDialog'; export * from './SystemCustomLabelDialog';
export * from './SystemLinkSignatureDialog'; export * from './SystemLinkSignatureDialog';

View File

@@ -0,0 +1,71 @@
import { WindowProps } from '@/hooks/Mapper/components/ui-kit/WindowManager/types.ts';
import {
LocalCharacters,
RoutesWidget,
SystemInfo,
SystemSignatures,
} from '@/hooks/Mapper/components/mapInterface/widgets';
export const CURRENT_WINDOWS_VERSION = 2;
export enum WidgetsIds {
info = 'info',
signatures = 'signatures',
local = 'local',
routes = 'routes',
}
export const DEFAULT_WIDGETS: WindowProps[] = [
{
id: WidgetsIds.info,
position: { x: 10, y: 10 },
size: { width: 250, height: 200 },
zIndex: 0,
content: () => <SystemInfo />,
},
{
id: WidgetsIds.signatures,
position: { x: 10, y: 220 },
size: { width: 250, height: 300 },
zIndex: 0,
content: () => <SystemSignatures />,
},
{
id: WidgetsIds.local,
position: { x: 270, y: 10 },
size: { width: 250, height: 510 },
zIndex: 0,
content: () => <LocalCharacters />,
},
{
id: WidgetsIds.routes,
position: { x: 10, y: 530 },
size: { width: 510, height: 200 },
zIndex: 0,
content: () => <RoutesWidget />,
},
];
type WidgetsCheckboxesType = {
id: WidgetsIds;
label: string;
}[];
export const WIDGETS_CHECKBOXES_PROPS: WidgetsCheckboxesType = [
{
id: WidgetsIds.info,
label: 'System Info',
},
{
id: WidgetsIds.signatures,
label: 'Signatures',
},
{
id: WidgetsIds.local,
label: 'Local',
},
{
id: WidgetsIds.routes,
label: 'Routes',
},
];

View File

@@ -3,13 +3,10 @@ import { Dialog } from 'primereact/dialog';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { TabPanel, TabView } from 'primereact/tabview'; import { TabPanel, TabView } from 'primereact/tabview';
import { PrettySwitchbox } from './components'; import { PrettySwitchbox } from './components';
import { import { InterfaceStoredSettingsProps, useMapRootState, InterfaceStoredSettings } from '@/hooks/Mapper/mapRootProvider';
InterfaceStoredSettingsProps,
useMapRootState,
InterfaceStoredSettings,
} from '@/hooks/Mapper/mapRootProvider';
import { OutCommand } from '@/hooks/Mapper/types'; import { OutCommand } from '@/hooks/Mapper/types';
import { Dropdown } from 'primereact/dropdown'; import { Dropdown } from 'primereact/dropdown';
import { WidgetsSettings } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/components/WidgetsSettings/WidgetsSettings.tsx';
export enum UserSettingsRemoteProps { export enum UserSettingsRemoteProps {
link_signature_on_splash = 'link_signature_on_splash', link_signature_on_splash = 'link_signature_on_splash',
@@ -140,7 +137,6 @@ export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
}; };
}, [userRemoteSettings, interfaceSettings]); }, [userRemoteSettings, interfaceSettings]);
const handleShow = async () => { const handleShow = async () => {
const { user_settings } = await outCommand({ const { user_settings } = await outCommand({
type: OutCommand.getUserSettings, type: OutCommand.getUserSettings,
@@ -182,7 +178,7 @@ export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
key={item.prop} key={item.prop}
label={item.label} label={item.label}
checked={!!currentValue} checked={!!currentValue}
setChecked={(checked) => handleSettingChange(item.prop, checked)} setChecked={checked => handleSettingChange(item.prop, checked)}
/> />
); );
} }
@@ -195,7 +191,7 @@ export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
className="text-sm" className="text-sm"
value={currentValue} value={currentValue}
options={item.options} options={item.options}
onChange={(e) => handleSettingChange(item.prop, e.value)} onChange={e => handleSettingChange(item.prop, e.value)}
placeholder="Select a theme" placeholder="Select a theme"
/> />
</div> </div>
@@ -227,19 +223,15 @@ export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
<div className={styles.verticalTabsContainer}> <div className={styles.verticalTabsContainer}>
<TabView <TabView
activeIndex={activeIndex} activeIndex={activeIndex}
onTabChange={(e) => setActiveIndex(e.index)} onTabChange={e => setActiveIndex(e.index)}
className={styles.verticalTabView} className={styles.verticalTabView}
> >
<TabPanel header="Common" headerClassName={styles.verticalTabHeader}> <TabPanel header="Common" headerClassName={styles.verticalTabHeader}>
<div className="w-full h-full flex flex-col gap-1"> <div className="w-full h-full flex flex-col gap-1">{renderSettingsList(COMMON_CHECKBOXES_PROPS)}</div>
{renderSettingsList(COMMON_CHECKBOXES_PROPS)}
</div>
</TabPanel> </TabPanel>
<TabPanel header="Systems" headerClassName={styles.verticalTabHeader}> <TabPanel header="Systems" headerClassName={styles.verticalTabHeader}>
<div className="w-full h-full flex flex-col gap-1"> <div className="w-full h-full flex flex-col gap-1">{renderSettingsList(SYSTEMS_CHECKBOXES_PROPS)}</div>
{renderSettingsList(SYSTEMS_CHECKBOXES_PROPS)}
</div>
</TabPanel> </TabPanel>
<TabPanel header="Connections" headerClassName={styles.verticalTabHeader}> <TabPanel header="Connections" headerClassName={styles.verticalTabHeader}>
@@ -254,6 +246,10 @@ export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
{renderSettingsList(UI_CHECKBOXES_PROPS)} {renderSettingsList(UI_CHECKBOXES_PROPS)}
</TabPanel> </TabPanel>
<TabPanel header="Widgets" headerClassName={styles.verticalTabHeader}>
<WidgetsSettings />
</TabPanel>
<TabPanel header="Theme" headerClassName={styles.verticalTabHeader}> <TabPanel header="Theme" headerClassName={styles.verticalTabHeader}>
{renderSettingItem(THEME_SETTING)} {renderSettingItem(THEME_SETTING)}
</TabPanel> </TabPanel>

View File

@@ -0,0 +1,37 @@
import { PrettySwitchbox } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/components';
import { WIDGETS_CHECKBOXES_PROPS, WidgetsIds } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useCallback } from 'react';
export interface WidgetsSettingsProps {}
// eslint-disable-next-line no-empty-pattern
export const WidgetsSettings = ({}: WidgetsSettingsProps) => {
const { windowsVisible, setWindowsVisible } = useMapRootState();
const handleWidgetSettingsChange = useCallback(
(widget: WidgetsIds, checked: boolean) => {
setWindowsVisible(prev => {
if (checked) {
return [...prev, widget];
}
return prev.filter(x => x !== widget);
});
},
[setWindowsVisible],
);
return (
<div className="">
{WIDGETS_CHECKBOXES_PROPS.map(widget => (
<PrettySwitchbox
key={widget.id}
label={widget.label}
checked={windowsVisible.some(x => x === widget.id)}
setChecked={checked => handleWidgetSettingsChange(widget.id, checked)}
/>
))}
</div>
);
};

View File

@@ -90,6 +90,16 @@ export const WindowManager: React.FC<WindowManagerProps> = ({ windows: initialWi
zIndex: index + 1, zIndex: index + 1,
})), })),
); );
useEffect(() => {
setWindows(
initialWindows.map((window, index) => ({
...window,
zIndex: index + 1,
})),
);
}, [initialWindows]);
const containerRef = useRef<HTMLDivElement | null>(null); const containerRef = useRef<HTMLDivElement | null>(null);
const activeWindowIdRef = useRef<string | number | null>(null); const activeWindowIdRef = useRef<string | number | null>(null);
const actionTypeRef = useRef<ActionType | null>(null); const actionTypeRef = useRef<ActionType | null>(null);

View File

@@ -6,4 +6,5 @@ export type WindowProps = {
position: { x: number; y: number }; position: { x: number; y: number };
size: { width: number; height: number }; size: { width: number; height: number };
zIndex: number; zIndex: number;
visible?: boolean;
}; };

View File

@@ -1,6 +1,7 @@
export enum SESSION_KEY { export enum SESSION_KEY {
viewPort = 'viewPort', viewPort = 'viewPort',
windows = 'windows', windows = 'windows',
windowsVisible = 'windowsVisible',
routes = 'routes', routes = 'routes',
} }

View File

@@ -4,6 +4,7 @@ import { MapUnionTypes, OutCommandHandler, SolarSystemConnection } from '@/hooks
import { useMapRootHandlers } from '@/hooks/Mapper/mapRootProvider/hooks'; import { useMapRootHandlers } from '@/hooks/Mapper/mapRootProvider/hooks';
import { WithChildren } from '@/hooks/Mapper/types/common.ts'; import { WithChildren } from '@/hooks/Mapper/types/common.ts';
import useLocalStorageState from 'use-local-storage-state'; import useLocalStorageState from 'use-local-storage-state';
import { WidgetsIds } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
export type MapRootData = MapUnionTypes & { export type MapRootData = MapUnionTypes & {
selectedSystems: string[]; selectedSystems: string[];
@@ -60,7 +61,14 @@ export const STORED_INTERFACE_DEFAULT_VALUES: InterfaceStoredSettings = {
isShowBackgroundPattern: true, isShowBackgroundPattern: true,
isSoftBackground: false, isSoftBackground: false,
theme: 'default', theme: 'default',
} };
export const STORED_VISIBLE_WIDGETS_DEFAULT = [
WidgetsIds.info,
WidgetsIds.local,
WidgetsIds.routes,
WidgetsIds.signatures,
];
export interface MapRootContextProps { export interface MapRootContextProps {
update: ContextStoreDataUpdate<MapRootData>; update: ContextStoreDataUpdate<MapRootData>;
@@ -68,6 +76,8 @@ export interface MapRootContextProps {
outCommand: OutCommandHandler; outCommand: OutCommandHandler;
interfaceSettings: InterfaceStoredSettings; interfaceSettings: InterfaceStoredSettings;
setInterfaceSettings: Dispatch<SetStateAction<InterfaceStoredSettings>>; setInterfaceSettings: Dispatch<SetStateAction<InterfaceStoredSettings>>;
windowsVisible: WidgetsIds[];
setWindowsVisible: Dispatch<SetStateAction<WidgetsIds[]>>;
} }
const MapRootContext = createContext<MapRootContextProps>({ const MapRootContext = createContext<MapRootContextProps>({
@@ -102,6 +112,10 @@ export const MapRootProvider = ({ children, fwdRef, outCommand }: MapRootProvide
}, },
); );
const [windowsVisible, setWindowsVisible] = useLocalStorageState<WidgetsIds[]>('windows:visible', {
defaultValue: STORED_VISIBLE_WIDGETS_DEFAULT,
});
useEffect(() => { useEffect(() => {
let foundNew = false; let foundNew = false;
const newVals = Object.keys(STORED_INTERFACE_DEFAULT_VALUES).reduce((acc, x) => { const newVals = Object.keys(STORED_INTERFACE_DEFAULT_VALUES).reduce((acc, x) => {
@@ -128,6 +142,8 @@ export const MapRootProvider = ({ children, fwdRef, outCommand }: MapRootProvide
outCommand: outCommand, outCommand: outCommand,
setInterfaceSettings, setInterfaceSettings,
interfaceSettings, interfaceSettings,
windowsVisible,
setWindowsVisible,
}} }}
> >
<MapRootHandlers ref={fwdRef}>{children}</MapRootHandlers> <MapRootHandlers ref={fwdRef}>{children}</MapRootHandlers>