mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-04 14:55:34 +00:00
fix(Map): Add style of corners for windows. Add ability to reset widgets. A lot of refactoring
This commit is contained in:
@@ -27,5 +27,5 @@
|
||||
--text-color: #ffffff;
|
||||
--tooltip-bg: #202020;
|
||||
|
||||
|
||||
--window-corner: #72716f;
|
||||
}
|
||||
|
||||
@@ -48,4 +48,6 @@
|
||||
|
||||
--rf-tag-color: #fbbf24;
|
||||
--rf-has-user-characters: #5cb85c;
|
||||
|
||||
--window-corner: #72716f;
|
||||
}
|
||||
@@ -1,63 +1,25 @@
|
||||
import 'react-grid-layout/css/styles.css';
|
||||
import 'react-resizable/css/styles.css';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { SESSION_KEY } from '@/hooks/Mapper/constants.ts';
|
||||
import { useMemo } from 'react';
|
||||
import { WindowManager } from '@/hooks/Mapper/components/ui-kit/WindowManager';
|
||||
import { WindowProps } from '@/hooks/Mapper/components/ui-kit/WindowManager/types.ts';
|
||||
import { CURRENT_WINDOWS_VERSION, DEFAULT_WIDGETS } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
|
||||
import { DEFAULT_WIDGETS } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
type WindowsLS = {
|
||||
windows: WindowProps[];
|
||||
version: number;
|
||||
};
|
||||
|
||||
const saveWindowsToLS = (toSaveItems: WindowProps[]) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const out = toSaveItems.map(({ content, ...rest }) => rest);
|
||||
localStorage.setItem(SESSION_KEY.windows, JSON.stringify({ version: CURRENT_WINDOWS_VERSION, windows: out }));
|
||||
};
|
||||
|
||||
const restoreWindowsFromLS = (): WindowProps[] => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const raw = localStorage.getItem(SESSION_KEY.windows);
|
||||
if (!raw) {
|
||||
console.warn('No windows found in local storage!!');
|
||||
return DEFAULT_WIDGETS;
|
||||
}
|
||||
|
||||
const { version, windows } = JSON.parse(raw) as WindowsLS;
|
||||
if (!version || CURRENT_WINDOWS_VERSION > version) {
|
||||
return DEFAULT_WIDGETS;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-debugger
|
||||
const out = (windows as Omit<WindowProps, 'content'>[])
|
||||
.filter(x => DEFAULT_WIDGETS.find(def => def.id === x.id))
|
||||
.map(x => {
|
||||
const content = DEFAULT_WIDGETS.find(def => def.id === x.id)?.content;
|
||||
return { ...x, content: content! };
|
||||
});
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
export const MapInterface = () => {
|
||||
const [items, setItems] = useState<WindowProps[]>(restoreWindowsFromLS);
|
||||
const { windowsVisible } = useMapRootState();
|
||||
// const [items, setItems] = useState<WindowProps[]>(restoreWindowsFromLS);
|
||||
const { windowsSettings, updateWidgetSettings } = useMapRootState();
|
||||
|
||||
const itemsFiltered = useMemo(() => {
|
||||
return items.filter(x => windowsVisible.some(j => x.id === j));
|
||||
}, [items, windowsVisible]);
|
||||
const items = useMemo(() => {
|
||||
return windowsSettings.windows
|
||||
.map(x => {
|
||||
const content = DEFAULT_WIDGETS.find(y => y.id === x.id)?.content;
|
||||
return {
|
||||
...x,
|
||||
content: content!,
|
||||
};
|
||||
})
|
||||
.filter(x => windowsSettings.visible.some(j => x.id === j));
|
||||
}, [windowsSettings]);
|
||||
|
||||
return (
|
||||
<WindowManager
|
||||
windows={itemsFiltered}
|
||||
dragSelector=".react-grid-dragHandleExample"
|
||||
onChange={x => {
|
||||
saveWindowsToLS(x);
|
||||
setItems(x);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
return <WindowManager windows={items} dragSelector=".react-grid-dragHandleExample" onChange={updateWidgetSettings} />;
|
||||
};
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
SystemSignatures,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets';
|
||||
|
||||
export const CURRENT_WINDOWS_VERSION = 2;
|
||||
export const CURRENT_WINDOWS_VERSION = 7;
|
||||
export const WINDOWS_LOCAL_STORE_KEY = 'windows:settings:v2';
|
||||
|
||||
export enum WidgetsIds {
|
||||
info = 'info',
|
||||
@@ -15,6 +16,13 @@ export enum WidgetsIds {
|
||||
routes = 'routes',
|
||||
}
|
||||
|
||||
export const STORED_VISIBLE_WIDGETS_DEFAULT = [
|
||||
WidgetsIds.info,
|
||||
WidgetsIds.local,
|
||||
WidgetsIds.routes,
|
||||
WidgetsIds.signatures,
|
||||
];
|
||||
|
||||
export const DEFAULT_WIDGETS: WindowProps[] = [
|
||||
{
|
||||
id: WidgetsIds.info,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
.p-tabview-panels {
|
||||
padding: 6px 1rem !important;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-tabview-nav-container {
|
||||
|
||||
@@ -221,11 +221,7 @@ export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className={styles.verticalTabsContainer}>
|
||||
<TabView
|
||||
activeIndex={activeIndex}
|
||||
onTabChange={e => setActiveIndex(e.index)}
|
||||
className={styles.verticalTabView}
|
||||
>
|
||||
<TabView activeIndex={activeIndex} onTabChange={e => setActiveIndex(e.index)}>
|
||||
<TabPanel header="Common" headerClassName={styles.verticalTabHeader}>
|
||||
<div className="w-full h-full flex flex-col gap-1">{renderSettingsList(COMMON_CHECKBOXES_PROPS)}</div>
|
||||
</TabPanel>
|
||||
@@ -246,7 +242,7 @@ export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
|
||||
{renderSettingsList(UI_CHECKBOXES_PROPS)}
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel header="Widgets" headerClassName={styles.verticalTabHeader}>
|
||||
<TabPanel header="Widgets" className="h-full" headerClassName={styles.verticalTabHeader}>
|
||||
<WidgetsSettings />
|
||||
</TabPanel>
|
||||
|
||||
|
||||
@@ -3,35 +3,35 @@ import { WIDGETS_CHECKBOXES_PROPS, WidgetsIds } from '@/hooks/Mapper/components/
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { Button } from 'primereact/button';
|
||||
|
||||
export interface WidgetsSettingsProps {}
|
||||
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
export const WidgetsSettings = ({}: WidgetsSettingsProps) => {
|
||||
const { windowsVisible, setWindowsVisible } = useMapRootState();
|
||||
const { windowsSettings, toggleWidgetVisibility, resetWidgets } = useMapRootState();
|
||||
|
||||
const handleWidgetSettingsChange = useCallback(
|
||||
(widget: WidgetsIds, checked: boolean) => {
|
||||
setWindowsVisible(prev => {
|
||||
if (checked) {
|
||||
return [...prev, widget];
|
||||
}
|
||||
|
||||
return prev.filter(x => x !== widget);
|
||||
});
|
||||
},
|
||||
[setWindowsVisible],
|
||||
(widget: WidgetsIds) => toggleWidgetVisibility(widget),
|
||||
[toggleWidgetVisibility],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="flex flex-col h-full gap-2">
|
||||
<div>
|
||||
{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)}
|
||||
checked={windowsSettings.visible.some(x => x === widget.id)}
|
||||
setChecked={() => handleWidgetSettingsChange(widget.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="grid grid-cols-[1fr_auto]">
|
||||
<div />
|
||||
<Button className="py-[4px]" onClick={resetWidgets} outlined size="small" label="Reset Widgets"></Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -35,21 +35,73 @@
|
||||
.topLeft {
|
||||
top: -7.5px;
|
||||
left: -7.5px;
|
||||
|
||||
&::after {
|
||||
position: relative;
|
||||
top: 7.5px;
|
||||
left: 7.5px;
|
||||
display: block;
|
||||
content: " ";
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-left: 1px solid var(--window-corner);
|
||||
border-top: 1px solid var(--window-corner);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.topRight {
|
||||
top: -7.5px;
|
||||
right: -7.5px;
|
||||
|
||||
&::after {
|
||||
position: relative;
|
||||
top: 7.5px;
|
||||
right: -2.5px;
|
||||
display: block;
|
||||
content: " ";
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-right: 1px solid var(--window-corner);
|
||||
border-top: 1px solid var(--window-corner);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.bottomLeft {
|
||||
bottom: -7.5px;
|
||||
left: -7.5px;
|
||||
|
||||
&::after {
|
||||
position: relative;
|
||||
top: 2.5px;
|
||||
left: 7.5px;
|
||||
display: block;
|
||||
content: " ";
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-left: 1px solid var(--window-corner);
|
||||
border-bottom: 1px solid var(--window-corner);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.bottomRight {
|
||||
bottom: -7.5px;
|
||||
right: -7.5px;
|
||||
|
||||
&::after {
|
||||
position: relative;
|
||||
top: 2.5px;
|
||||
right: -2.5px;
|
||||
display: block;
|
||||
content: " ";
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-right: 1px solid var(--window-corner);
|
||||
border-bottom: 1px solid var(--window-corner);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.top {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { WindowProps } from '@/hooks/Mapper/components/ui-kit/WindowManager/type
|
||||
|
||||
const MIN_WINDOW_SIZE = 100;
|
||||
const SNAP_THRESHOLD = 10;
|
||||
const SNAP_GAP = 10;
|
||||
export const SNAP_GAP = 10;
|
||||
|
||||
export enum ActionType {
|
||||
Drag = 'drag',
|
||||
@@ -92,12 +92,7 @@ export const WindowManager: React.FC<WindowManagerProps> = ({ windows: initialWi
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setWindows(
|
||||
initialWindows.map((window, index) => ({
|
||||
...window,
|
||||
zIndex: index + 1,
|
||||
})),
|
||||
);
|
||||
setWindows(initialWindows.slice(0));
|
||||
}, [initialWindows]);
|
||||
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
@@ -4,7 +4,12 @@ import { MapUnionTypes, OutCommandHandler, SolarSystemConnection } from '@/hooks
|
||||
import { useMapRootHandlers } from '@/hooks/Mapper/mapRootProvider/hooks';
|
||||
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import { WidgetsIds } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
|
||||
import {
|
||||
ToggleWidgetVisibility,
|
||||
UpdateWidgetSettingsFunc,
|
||||
useStoreWidgets,
|
||||
WindowStoreInfo,
|
||||
} from '@/hooks/Mapper/mapRootProvider/hooks/useStoreWidgets.ts';
|
||||
|
||||
export type MapRootData = MapUnionTypes & {
|
||||
selectedSystems: string[];
|
||||
@@ -64,21 +69,16 @@ export const STORED_INTERFACE_DEFAULT_VALUES: InterfaceStoredSettings = {
|
||||
theme: 'default',
|
||||
};
|
||||
|
||||
export const STORED_VISIBLE_WIDGETS_DEFAULT = [
|
||||
WidgetsIds.info,
|
||||
WidgetsIds.local,
|
||||
WidgetsIds.routes,
|
||||
WidgetsIds.signatures,
|
||||
];
|
||||
|
||||
export interface MapRootContextProps {
|
||||
update: ContextStoreDataUpdate<MapRootData>;
|
||||
data: MapRootData;
|
||||
outCommand: OutCommandHandler;
|
||||
interfaceSettings: InterfaceStoredSettings;
|
||||
setInterfaceSettings: Dispatch<SetStateAction<InterfaceStoredSettings>>;
|
||||
windowsVisible: WidgetsIds[];
|
||||
setWindowsVisible: Dispatch<SetStateAction<WidgetsIds[]>>;
|
||||
windowsSettings: WindowStoreInfo;
|
||||
toggleWidgetVisibility: ToggleWidgetVisibility;
|
||||
updateWidgetSettings: UpdateWidgetSettingsFunc;
|
||||
resetWidgets: () => void;
|
||||
}
|
||||
|
||||
const MapRootContext = createContext<MapRootContextProps>({
|
||||
@@ -112,10 +112,7 @@ export const MapRootProvider = ({ children, fwdRef, outCommand }: MapRootProvide
|
||||
defaultValue: STORED_INTERFACE_DEFAULT_VALUES,
|
||||
},
|
||||
);
|
||||
|
||||
const [windowsVisible, setWindowsVisible] = useLocalStorageState<WidgetsIds[]>('windows:visible', {
|
||||
defaultValue: STORED_VISIBLE_WIDGETS_DEFAULT,
|
||||
});
|
||||
const { windowsSettings, toggleWidgetVisibility, updateWidgetSettings, resetWidgets } = useStoreWidgets();
|
||||
|
||||
useEffect(() => {
|
||||
let foundNew = false;
|
||||
@@ -143,8 +140,10 @@ export const MapRootProvider = ({ children, fwdRef, outCommand }: MapRootProvide
|
||||
outCommand: outCommand,
|
||||
setInterfaceSettings,
|
||||
interfaceSettings,
|
||||
windowsVisible,
|
||||
setWindowsVisible,
|
||||
windowsSettings,
|
||||
updateWidgetSettings,
|
||||
toggleWidgetVisibility,
|
||||
resetWidgets,
|
||||
}}
|
||||
>
|
||||
<MapRootHandlers ref={fwdRef}>{children}</MapRootHandlers>
|
||||
|
||||
118
assets/js/hooks/Mapper/mapRootProvider/hooks/useStoreWidgets.ts
Normal file
118
assets/js/hooks/Mapper/mapRootProvider/hooks/useStoreWidgets.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import {
|
||||
CURRENT_WINDOWS_VERSION,
|
||||
DEFAULT_WIDGETS,
|
||||
STORED_VISIBLE_WIDGETS_DEFAULT,
|
||||
WidgetsIds,
|
||||
WINDOWS_LOCAL_STORE_KEY,
|
||||
} from '@/hooks/Mapper/components/mapInterface/constants.tsx';
|
||||
import { WindowProps } from '@/hooks/Mapper/components/ui-kit/WindowManager/types.ts';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { SNAP_GAP } from '@/hooks/Mapper/components/ui-kit/WindowManager';
|
||||
|
||||
export type StoredWindowProps = Omit<WindowProps, 'content'>;
|
||||
export type WindowStoreInfo = {
|
||||
version: number;
|
||||
windows: StoredWindowProps[];
|
||||
visible: WidgetsIds[];
|
||||
};
|
||||
export type UpdateWidgetSettingsFunc = (widgets: WindowProps[]) => void;
|
||||
export type ToggleWidgetVisibility = (widgetId: WidgetsIds) => void;
|
||||
|
||||
export const getDefaultWidgetProps = () => ({
|
||||
version: CURRENT_WINDOWS_VERSION,
|
||||
visible: STORED_VISIBLE_WIDGETS_DEFAULT,
|
||||
windows: DEFAULT_WIDGETS,
|
||||
});
|
||||
|
||||
export const useStoreWidgets = () => {
|
||||
const [windowsSettings, setWindowsSettings] = useLocalStorageState<WindowStoreInfo>(WINDOWS_LOCAL_STORE_KEY, {
|
||||
defaultValue: getDefaultWidgetProps(),
|
||||
});
|
||||
|
||||
const ref = useRef({ windowsSettings, setWindowsSettings });
|
||||
ref.current = { windowsSettings, setWindowsSettings };
|
||||
|
||||
const updateWidgetSettings: UpdateWidgetSettingsFunc = useCallback(newWindows => {
|
||||
const { setWindowsSettings } = ref.current;
|
||||
|
||||
setWindowsSettings(({ version, visible /*, windows*/ }: WindowStoreInfo) => {
|
||||
return {
|
||||
version,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
windows: DEFAULT_WIDGETS.map(({ content, ...x }) => {
|
||||
const windowProp = newWindows.find(j => j.id === x.id);
|
||||
if (windowProp) {
|
||||
return windowProp;
|
||||
}
|
||||
|
||||
return x;
|
||||
}),
|
||||
visible,
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
const toggleWidgetVisibility: ToggleWidgetVisibility = useCallback(widgetId => {
|
||||
const { setWindowsSettings } = ref.current;
|
||||
|
||||
setWindowsSettings(({ visible, windows, ...x }) => {
|
||||
const isCheckedPrev = visible.includes(widgetId);
|
||||
if (!isCheckedPrev) {
|
||||
const maxZIndex = Math.max(...windows.map(w => w.zIndex));
|
||||
return {
|
||||
...x,
|
||||
windows: windows.map(wnd => {
|
||||
if (wnd.id === widgetId) {
|
||||
return { ...wnd, position: { x: SNAP_GAP, y: SNAP_GAP }, zIndex: maxZIndex + 1 };
|
||||
}
|
||||
|
||||
return wnd;
|
||||
}),
|
||||
visible: [...visible, widgetId],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...x,
|
||||
windows,
|
||||
visible: visible.filter(x => x !== widgetId),
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const { setWindowsSettings } = ref.current;
|
||||
|
||||
const raw = localStorage.getItem(WINDOWS_LOCAL_STORE_KEY);
|
||||
if (!raw) {
|
||||
console.warn('No windows found in local storage!!');
|
||||
|
||||
setWindowsSettings(getDefaultWidgetProps());
|
||||
return;
|
||||
}
|
||||
|
||||
const { version, windows, visible } = JSON.parse(raw) as WindowStoreInfo;
|
||||
if (!version || CURRENT_WINDOWS_VERSION > version) {
|
||||
setWindowsSettings(getDefaultWidgetProps());
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-debugger
|
||||
const out = windows.filter(x => DEFAULT_WIDGETS.find(def => def.id === x.id));
|
||||
|
||||
setWindowsSettings({
|
||||
version: CURRENT_WINDOWS_VERSION,
|
||||
windows: out as WindowProps[],
|
||||
visible,
|
||||
});
|
||||
}, []);
|
||||
|
||||
const resetWidgets = useCallback(() => ref.current.setWindowsSettings(getDefaultWidgetProps()), []);
|
||||
|
||||
return {
|
||||
windowsSettings,
|
||||
updateWidgetSettings,
|
||||
toggleWidgetVisibility,
|
||||
resetWidgets,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user