Files
wanderer/assets/js/hooks/Mapper/mapRootProvider/MapRootProvider.tsx
Aleksei Chichenkov d8222d83f0 Refactoring and fixing problems (#317)
* fix(Map): fix design of kills widget, fix design of signatures widget - refactor a lot of code, fixed problem with tooltip blinking

* fix(Map): refactor Tracking dialog, refactor Activity tracker, refactor codebase and some styles

* fix(Core): don't count character passage on manual add connection

* refactor(Core): improved characters tracking API

* fix(Core): fixed link signature to system on 'leads to' set

* fix(Map): Refactor map settings and prepared it to easier using

* fix(Map): Add support new command for following update

* fix(Map): Add support new command for main update

* refactor(Core): Reduce map init data by using cached system static data

* refactor(Core): Reduce map init data by extract signatures loading to a separate event

* fix(Core): adjusted IP rate limits

* fix(Map): Update design of tracking characters. Added icons for following and main. Added ability to see that character on the station or structure

---------

Co-authored-by: achichenkov <aleksei.chichenkov@telleqt.ai>
Co-authored-by: Dmitry Popov <dmitriypopovsamara@gmail.com>
2025-04-11 23:17:53 +04:00

216 lines
6.2 KiB
TypeScript

import { ContextStoreDataUpdate, useContextStore } from '@/hooks/Mapper/utils';
import { createContext, Dispatch, ForwardedRef, forwardRef, SetStateAction, useContext, useEffect } from 'react';
import {
ActivitySummary,
CommandLinkSignatureToSystem,
MapUnionTypes,
OutCommandHandler,
SolarSystemConnection,
TrackingCharacter,
UseCharactersCacheData,
UseCommentsData,
} from '@/hooks/Mapper/types';
import { useCharactersCache, useComments, useMapRootHandlers } from '@/hooks/Mapper/mapRootProvider/hooks';
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
import useLocalStorageState from 'use-local-storage-state';
import {
ToggleWidgetVisibility,
useStoreWidgets,
WindowStoreInfo,
} from '@/hooks/Mapper/mapRootProvider/hooks/useStoreWidgets.ts';
import { WindowsManagerOnChange } from '@/hooks/Mapper/components/ui-kit/WindowManager';
import { DetailedKill } from '../types/kills';
export type MapRootData = MapUnionTypes & {
selectedSystems: string[];
selectedConnections: Pick<SolarSystemConnection, 'source' | 'target'>[];
linkSignatureToSystem: CommandLinkSignatureToSystem | null;
detailedKills: Record<string, DetailedKill[]>;
showCharacterActivity: boolean;
characterActivityData: {
activity: ActivitySummary[];
loading?: boolean;
};
trackingCharactersData: TrackingCharacter[];
};
const INITIAL_DATA: MapRootData = {
wormholesData: {},
wormholes: [],
effects: {},
characters: [],
showCharacterActivity: false,
characterActivityData: {
activity: [],
loading: false,
},
trackingCharactersData: [],
userCharacters: [],
presentCharacters: [],
systems: [],
systemSignatures: {},
hubs: [],
routes: undefined,
kills: [],
connections: [],
detailedKills: {},
selectedSystems: [],
selectedConnections: [],
userPermissions: {},
options: {},
isSubscriptionActive: false,
linkSignatureToSystem: null,
mainCharacterEveId: null,
followingCharacterEveId: null,
};
export enum AvailableThemes {
default = 'default',
pathfinder = 'pathfinder',
}
export enum InterfaceStoredSettingsProps {
isShowMenu = 'isShowMenu',
isShowMinimap = 'isShowMinimap',
isShowKSpace = 'isShowKSpace',
isThickConnections = 'isThickConnections',
isShowUnsplashedSignatures = 'isShowUnsplashedSignatures',
isShowBackgroundPattern = 'isShowBackgroundPattern',
isSoftBackground = 'isSoftBackground',
theme = 'theme',
}
export type InterfaceStoredSettings = {
isShowMenu: boolean;
isShowMinimap: boolean;
isShowKSpace: boolean;
isThickConnections: boolean;
isShowUnsplashedSignatures: boolean;
isShowBackgroundPattern: boolean;
isSoftBackground: boolean;
theme: AvailableThemes;
};
export const STORED_INTERFACE_DEFAULT_VALUES: InterfaceStoredSettings = {
isShowMenu: false,
isShowMinimap: true,
isShowKSpace: false,
isThickConnections: false,
isShowUnsplashedSignatures: false,
isShowBackgroundPattern: true,
isSoftBackground: false,
theme: AvailableThemes.default,
};
export interface MapRootContextProps {
update: ContextStoreDataUpdate<MapRootData>;
data: MapRootData;
outCommand: OutCommandHandler;
interfaceSettings: InterfaceStoredSettings;
setInterfaceSettings: Dispatch<SetStateAction<InterfaceStoredSettings>>;
windowsSettings: WindowStoreInfo;
toggleWidgetVisibility: ToggleWidgetVisibility;
updateWidgetSettings: WindowsManagerOnChange;
resetWidgets: () => void;
comments: UseCommentsData;
charactersCache: UseCharactersCacheData;
}
const MapRootContext = createContext<MapRootContextProps>({
update: () => {},
data: { ...INITIAL_DATA },
// @ts-ignore
outCommand: async () => void 0,
interfaceSettings: STORED_INTERFACE_DEFAULT_VALUES,
setInterfaceSettings: () => null,
comments: {
loadComments: async () => {},
comments: new Map(),
lastUpdateKey: 0,
addComment: function (): void {
throw new Error('Function not implemented.');
},
removeComment: function (): void {
throw new Error('Function not implemented.');
},
},
charactersCache: {
loadCharacter: function (): Promise<void> {
throw new Error('Function not implemented.');
},
characters: new Map(),
lastUpdateKey: 0,
},
});
type MapRootProviderProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fwdRef: ForwardedRef<any>;
outCommand: OutCommandHandler;
} & WithChildren;
// eslint-disable-next-line react/display-name
const MapRootHandlers = forwardRef(({ children }: WithChildren, fwdRef: ForwardedRef<any>) => {
useMapRootHandlers(fwdRef);
return <>{children}</>;
});
// eslint-disable-next-line react/display-name
export const MapRootProvider = ({ children, fwdRef, outCommand }: MapRootProviderProps) => {
const { update, ref } = useContextStore<MapRootData>({ ...INITIAL_DATA });
const [interfaceSettings, setInterfaceSettings] = useLocalStorageState<InterfaceStoredSettings>(
'window:interface:settings',
{
defaultValue: STORED_INTERFACE_DEFAULT_VALUES,
},
);
const { windowsSettings, toggleWidgetVisibility, updateWidgetSettings, resetWidgets } = useStoreWidgets();
const comments = useComments({ outCommand });
const charactersCache = useCharactersCache({ outCommand });
useEffect(() => {
let foundNew = false;
const newVals = Object.keys(STORED_INTERFACE_DEFAULT_VALUES).reduce((acc, x) => {
if (Object.keys(acc).includes(x)) {
return acc;
}
foundNew = true;
// @ts-ignore
return { ...acc, [x]: STORED_INTERFACE_DEFAULT_VALUES[x] };
}, interfaceSettings);
if (foundNew) {
setInterfaceSettings(newVals);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<MapRootContext.Provider
value={{
update,
data: ref,
outCommand,
setInterfaceSettings,
interfaceSettings,
windowsSettings,
updateWidgetSettings,
toggleWidgetVisibility,
resetWidgets,
comments,
charactersCache,
}}
>
<MapRootHandlers ref={fwdRef}>{children}</MapRootHandlers>
</MapRootContext.Provider>
);
};
export const useMapRootState = () => {
const context = useContext<MapRootContextProps>(MapRootContext);
return context;
};