Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69eb888469 | ||
|
|
748347df9a | ||
|
|
aa4d49027c | ||
|
|
a9d7387e40 | ||
|
|
dc4d260c9b | ||
|
|
dc430491bf | ||
|
|
42cd261ea7 | ||
|
|
35af4fdc09 | ||
|
|
8bb4998e59 | ||
|
|
c825a3f4c4 | ||
|
|
5343c34488 | ||
|
|
4878be1a53 | ||
|
|
1ff689c26c | ||
|
|
79b660e899 | ||
|
|
665a679bd5 | ||
|
|
7bd634eb95 | ||
|
|
c3b5a77a86 | ||
|
|
8498846d9c | ||
|
|
12f39a0133 | ||
|
|
ffc2a86e95 | ||
|
|
82babf41a2 | ||
|
|
81055b4fbd | ||
|
|
5070a59f88 | ||
|
|
65d5bf960d | ||
|
|
8fc4cb190e | ||
|
|
c6c065dbb9 | ||
|
|
8ba34533d7 | ||
|
|
095a4b2362 | ||
|
|
fafc631e49 | ||
|
|
e56383c8b1 | ||
|
|
b9c26bdb04 | ||
|
|
8aeaa81752 | ||
|
|
b16ec0490f | ||
|
|
eceaf1d73b | ||
|
|
34cf668a33 | ||
|
|
c22d410c9f | ||
|
|
fc6af867f2 | ||
|
|
2d96114984 | ||
|
|
fd7e19e490 | ||
|
|
f7d996f5b2 | ||
|
|
f8ab1383ab | ||
|
|
e1559aac94 | ||
|
|
2e17cce5cd | ||
|
|
8fb831f171 | ||
|
|
cb84f34515 | ||
|
|
272cce1a77 | ||
|
|
e0e3ed1580 | ||
|
|
c4c848cf37 | ||
|
|
d33a2e3a5b | ||
|
|
5c8753fb96 | ||
|
|
32d25d86eb | ||
|
|
863adccac1 | ||
|
|
2d527e1d16 | ||
|
|
9a64ad6fa7 | ||
|
|
5ce472ebff | ||
|
|
76588af12f | ||
|
|
134f169eb9 | ||
|
|
7c2d731c4c | ||
|
|
c7e2a290cf | ||
|
|
5ea966892a | ||
|
|
b879db76b7 | ||
|
|
d13a628029 | ||
|
|
7c1e2595e3 | ||
|
|
a99e8a915e | ||
|
|
36f424da0b | ||
|
|
c0a65d5a23 | ||
|
|
02e31333d2 | ||
|
|
d69616119d | ||
|
|
f89cd5f44f | ||
|
|
abe4951251 | ||
|
|
dbc770d40b | ||
|
|
e69a8fece5 | ||
|
|
3b24c760ff | ||
|
|
3801f0be18 | ||
|
|
5508fbee2f | ||
|
|
51ff4e7f36 | ||
|
|
f3104db2e4 | ||
|
|
34d3d92afd | ||
|
|
c789b69b54 | ||
|
|
302fb0642d | ||
|
|
33acd55eaa |
@@ -13,4 +13,4 @@ export WANDERER_KILLS_BASE_URL="ws://host.docker.internal:4004"
|
||||
export WANDERER_SSE_ENABLED="true"
|
||||
export WANDERER_WEBHOOKS_ENABLED="true"
|
||||
export WANDERER_SSE_MAX_CONNECTIONS="1000"
|
||||
export WANDERER_WEBHOOK_TIMEOUT_MS="15000"
|
||||
export WANDERER_WEBHOOK_TIMEOUT_MS="15000"
|
||||
|
||||
169
CHANGELOG.md
@@ -2,6 +2,175 @@
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.81.8](https://github.com/wanderer-industries/wanderer/compare/v1.81.7...v1.81.8) (2025-10-11)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fix problem with restoring settings on widgets
|
||||
|
||||
## [v1.81.7](https://github.com/wanderer-industries/wanderer/compare/v1.81.6...v1.81.7) (2025-10-10)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fixed problem with rendering dropdown classes in signatures
|
||||
|
||||
## [v1.81.6](https://github.com/wanderer-industries/wanderer/compare/v1.81.5...v1.81.6) (2025-10-10)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fixed problem with a lot unnecessary loads zkb data on resize map
|
||||
|
||||
* Map: Added ability to see focused element
|
||||
|
||||
* Map: Removed unnecessary vertical scroller in Character Tracking dialog. Main always first in list of tracking characters, following next after main, another characters sorting by name
|
||||
|
||||
* Map: Added Search tool for systems what on the map
|
||||
|
||||
* Map: Added migration mechanism
|
||||
|
||||
* Map: Remove settings some default values if migration from very old settings system
|
||||
|
||||
* Map: MIGRATION: support from old store settings import
|
||||
|
||||
* Map: Add common migration mechanism. ATTENTION! This is a non-reversible stored map settings commit â it means we do not guarantee that settings will work if you check out back. Weâve tried to migrate old settings, but it may not work well or may NOT work at all.
|
||||
|
||||
* Map: Add front-end migrations for local store settings
|
||||
|
||||
## [v1.81.5](https://github.com/wanderer-industries/wanderer/compare/v1.81.4...v1.81.5) (2025-10-09)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Update connection ship size based on linked signature type
|
||||
|
||||
## [v1.81.4](https://github.com/wanderer-industries/wanderer/compare/v1.81.3...v1.81.4) (2025-10-09)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed signature to system link issues
|
||||
|
||||
## [v1.81.3](https://github.com/wanderer-industries/wanderer/compare/v1.81.2...v1.81.3) (2025-10-07)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed cancel ping errors
|
||||
|
||||
## [v1.81.2](https://github.com/wanderer-industries/wanderer/compare/v1.81.1...v1.81.2) (2025-10-07)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* api dropping custom name
|
||||
|
||||
## [v1.81.1](https://github.com/wanderer-industries/wanderer/compare/v1.81.0...v1.81.1) (2025-10-02)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed characters tracking updates.
|
||||
|
||||
## [v1.81.0](https://github.com/wanderer-industries/wanderer/compare/v1.80.0...v1.81.0) (2025-10-02)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* core: fix pwa icons + add screen in manifest
|
||||
|
||||
## [v1.80.0](https://github.com/wanderer-industries/wanderer/compare/v1.79.6...v1.80.0) (2025-10-02)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Core: Added PWA web manifest
|
||||
|
||||
## [v1.79.6](https://github.com/wanderer-industries/wanderer/compare/v1.79.5...v1.79.6) (2025-10-01)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed modals auto-save on Enter.
|
||||
|
||||
## [v1.79.5](https://github.com/wanderer-industries/wanderer/compare/v1.79.4...v1.79.5) (2025-10-01)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed system details modal auto-save on Enter.
|
||||
|
||||
## [v1.79.4](https://github.com/wanderer-industries/wanderer/compare/v1.79.3...v1.79.4) (2025-09-30)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed updating connection time status based on linked signature data. Fixed FR gas sites parsing.
|
||||
|
||||
## [v1.79.3](https://github.com/wanderer-industries/wanderer/compare/v1.79.2...v1.79.3) (2025-09-27)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Core: Fixed connection passages count
|
||||
|
||||
## [v1.79.2](https://github.com/wanderer-industries/wanderer/compare/v1.79.1...v1.79.2) (2025-09-26)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.79.1](https://github.com/wanderer-industries/wanderer/compare/v1.79.0...v1.79.1) (2025-09-26)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.79.0](https://github.com/wanderer-industries/wanderer/compare/v1.78.1...v1.79.0) (2025-09-26)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Core: Updated connections EOL logic
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fixed eslint problems
|
||||
|
||||
* Map: Update lifetime design and buttons
|
||||
|
||||
* Map: Update wormhole lifetime UI and removed unnecessary code
|
||||
|
||||
## [v1.78.1](https://github.com/wanderer-industries/wanderer/compare/v1.78.0...v1.78.1) (2025-09-24)
|
||||
|
||||
|
||||
|
||||
@@ -18,5 +18,28 @@ module.exports = {
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
"linebreak-style": "off",
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"name": "primereact/button",
|
||||
"importNames": ["Button"],
|
||||
"message": "Use WdButton instead Button"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"react/forbid-elements": [
|
||||
"error",
|
||||
{
|
||||
"forbid": [
|
||||
{
|
||||
"element": "Button",
|
||||
"message": "Use WdButton instead Button"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
@@ -284,3 +284,7 @@
|
||||
border-left-color: #e67e22;
|
||||
}
|
||||
|
||||
.p-dialog-header-icon.p-dialog-header-close.p-link {
|
||||
position: relative;
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.vertical-tabs-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-height: 400px;
|
||||
min-height: 200px;
|
||||
|
||||
.p-tabview {
|
||||
width: 100%;
|
||||
|
||||
@@ -5,8 +5,7 @@ import { SolarSystemRawType } from '@/hooks/Mapper/types';
|
||||
import { getSystemById } from '@/hooks/Mapper/helpers';
|
||||
import clsx from 'clsx';
|
||||
import { GRADIENT_MENU_ACTIVE_CLASSES } from '@/hooks/Mapper/constants.ts';
|
||||
import { LayoutEventBlocker } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { Button } from 'primereact/button';
|
||||
import { LayoutEventBlocker, WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
const AVAILABLE_TAGS = [
|
||||
'A',
|
||||
@@ -61,7 +60,7 @@ export const useTagMenu = (
|
||||
<LayoutEventBlocker className="flex flex-col gap-1 w-[200px] h-full px-2">
|
||||
<div className="grid grid-cols-[auto_auto_auto_auto_auto_auto] gap-1">
|
||||
{AVAILABLE_TAGS.map(x => (
|
||||
<Button
|
||||
<WdButton
|
||||
outlined={system?.tag !== x}
|
||||
severity="warning"
|
||||
key={x}
|
||||
@@ -71,9 +70,9 @@ export const useTagMenu = (
|
||||
onClick={() => system?.tag !== x && onSystemTag(x)}
|
||||
>
|
||||
{x}
|
||||
</Button>
|
||||
</WdButton>
|
||||
))}
|
||||
<Button
|
||||
<WdButton
|
||||
disabled={!isSelectedTag}
|
||||
icon="pi pi-ban"
|
||||
size="small"
|
||||
@@ -81,7 +80,7 @@ export const useTagMenu = (
|
||||
outlined
|
||||
severity="help"
|
||||
onClick={() => onSystemTag()}
|
||||
></Button>
|
||||
></WdButton>
|
||||
</div>
|
||||
</LayoutEventBlocker>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MapUserSettings, SettingsWithVersion } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { MapUserSettings, SettingsWrapper } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
|
||||
export const REQUIRED_KEYS = [
|
||||
'widgets',
|
||||
@@ -19,11 +19,8 @@ export class MapUserSettingsParseError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
const isNumber = (v: unknown): v is number => typeof v === 'number' && !Number.isNaN(v);
|
||||
|
||||
/** Minimal check that an object matches SettingsWithVersion<*> */
|
||||
const isSettingsWithVersion = (v: unknown): v is SettingsWithVersion<unknown> =>
|
||||
typeof v === 'object' && v !== null && isNumber((v as any).version) && 'settings' in (v as any);
|
||||
/** Minimal check that an object matches SettingsWrapper<*> */
|
||||
const isSettings = (v: unknown): v is SettingsWrapper<unknown> => typeof v === 'object' && v !== null;
|
||||
|
||||
/** Ensure every required key is present */
|
||||
const hasAllRequiredKeys = (v: unknown): v is Record<RequiredKeys, unknown> =>
|
||||
@@ -52,8 +49,8 @@ export const parseMapUserSettings = (json: unknown): MapUserSettings => {
|
||||
}
|
||||
|
||||
for (const key of REQUIRED_KEYS) {
|
||||
if (!isSettingsWithVersion((data as any)[key])) {
|
||||
throw new MapUserSettingsParseError(`"${key}" must match SettingsWithVersion<T>`);
|
||||
if (!isSettings((data as any)[key])) {
|
||||
throw new MapUserSettingsParseError(`"${key}" must match SettingsWrapper<T>`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
26
assets/js/hooks/Mapper/components/hooks/useLocalCounter.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useMemo } from 'react';
|
||||
import { CharacterTypeRaw } from '@/hooks/Mapper/types';
|
||||
|
||||
export type UseLocalCounterProps = {
|
||||
charactersInSystem: Array<CharacterTypeRaw>;
|
||||
userCharacters: string[];
|
||||
};
|
||||
|
||||
export const getLocalCharacters = ({ charactersInSystem, userCharacters }: UseLocalCounterProps) => {
|
||||
return charactersInSystem
|
||||
.map(char => ({
|
||||
...char,
|
||||
compact: true,
|
||||
isOwn: userCharacters.includes(char.eve_id),
|
||||
}))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
};
|
||||
|
||||
export const useLocalCounter = ({ charactersInSystem, userCharacters }: UseLocalCounterProps) => {
|
||||
const localCounterCharacters = useMemo(
|
||||
() => getLocalCharacters({ charactersInSystem, userCharacters }),
|
||||
[charactersInSystem, userCharacters],
|
||||
);
|
||||
|
||||
return { localCounterCharacters };
|
||||
};
|
||||
@@ -1,11 +1,10 @@
|
||||
import { NodeSelectionMouseHandler } from '@/hooks/Mapper/components/contexts/types.ts';
|
||||
import { SESSION_KEY } from '@/hooks/Mapper/constants.ts';
|
||||
import { PingData, SolarSystemConnection, SolarSystemRawType } from '@/hooks/Mapper/types';
|
||||
import { MapHandlers, OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts';
|
||||
import type { PanelPosition } from '@reactflow/core';
|
||||
import clsx from 'clsx';
|
||||
import { ForwardedRef, forwardRef, MouseEvent, useCallback, useEffect, useMemo } from 'react';
|
||||
import { ForwardedRef, forwardRef, MouseEvent, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import ReactFlow, {
|
||||
Background,
|
||||
Edge,
|
||||
@@ -33,19 +32,9 @@ import {
|
||||
import { getBehaviorForTheme } from './helpers/getThemeBehavior';
|
||||
import { useEdgesState, useMapHandlers, useNodesState, useUpdateNodes } from './hooks';
|
||||
import { useBackgroundVars } from './hooks/useBackgroundVars';
|
||||
import { OnMapAddSystemCallback, OnMapSelectionChange } from './map.types';
|
||||
|
||||
const DEFAULT_VIEW_PORT = { zoom: 1, x: 0, y: 0 };
|
||||
|
||||
const getViewPortFromStore = () => {
|
||||
const restored = localStorage.getItem(SESSION_KEY.viewPort);
|
||||
|
||||
if (!restored) {
|
||||
return { ...DEFAULT_VIEW_PORT };
|
||||
}
|
||||
|
||||
return JSON.parse(restored);
|
||||
};
|
||||
import { MapViewport, OnMapAddSystemCallback, OnMapSelectionChange } from './map.types';
|
||||
import type { Viewport } from '@reactflow/core/dist/esm/types';
|
||||
import { usePrevious } from 'primereact/hooks';
|
||||
|
||||
const initialNodes: Node<SolarSystemRawType>[] = [
|
||||
// {
|
||||
@@ -88,6 +77,7 @@ interface MapCompProps {
|
||||
onConnectionInfoClick?(e: SolarSystemConnection): void;
|
||||
onAddSystem?: OnMapAddSystemCallback;
|
||||
onSelectionContextMenu?: NodeSelectionMouseHandler;
|
||||
onChangeViewport?: (viewport: MapViewport) => void;
|
||||
minimapClasses?: string;
|
||||
isShowMinimap?: boolean;
|
||||
onSystemContextMenu: (event: MouseEvent<Element>, systemId: string) => void;
|
||||
@@ -99,6 +89,7 @@ interface MapCompProps {
|
||||
pings: PingData[];
|
||||
minimapPlacement?: PanelPosition;
|
||||
localShowShipName?: boolean;
|
||||
defaultViewport?: Viewport;
|
||||
}
|
||||
|
||||
const MapComp = ({
|
||||
@@ -119,19 +110,25 @@ const MapComp = ({
|
||||
pings,
|
||||
minimapPlacement = 'bottom-right',
|
||||
localShowShipName = false,
|
||||
onChangeViewport,
|
||||
defaultViewport,
|
||||
}: MapCompProps) => {
|
||||
const { getNodes } = useReactFlow();
|
||||
const { getNodes, setViewport } = useReactFlow();
|
||||
const [nodes, , onNodesChange] = useNodesState<Node<SolarSystemRawType>>(initialNodes);
|
||||
const [edges, , onEdgesChange] = useEdgesState<Edge<SolarSystemConnection>>(initialEdges);
|
||||
|
||||
useMapHandlers(refn, onSelectionChange);
|
||||
useUpdateNodes(nodes);
|
||||
|
||||
const { handleRootContext, ...rootCtxProps } = useContextMenuRootHandlers({ onAddSystem });
|
||||
const { handleConnectionContext, ...connectionCtxProps } = useContextMenuConnectionHandlers();
|
||||
const { update } = useMapState();
|
||||
const { variant, gap, size, color } = useBackgroundVars(theme);
|
||||
const { isPanAndDrag, nodeComponent, connectionMode } = getBehaviorForTheme(theme || 'default');
|
||||
|
||||
const refVars = useRef({ onChangeViewport });
|
||||
refVars.current = { onChangeViewport };
|
||||
|
||||
const nodeTypes = useMemo(() => {
|
||||
return {
|
||||
custom: nodeComponent,
|
||||
@@ -187,9 +184,10 @@ const MapComp = ({
|
||||
[onSelectionChange],
|
||||
);
|
||||
|
||||
const handleMoveEnd: OnMoveEnd = (_, viewport) => {
|
||||
localStorage.setItem(SESSION_KEY.viewPort, JSON.stringify(viewport));
|
||||
};
|
||||
const handleMoveEnd: OnMoveEnd = useCallback((_, viewport) => {
|
||||
// @ts-ignore
|
||||
refVars.current.onChangeViewport?.(viewport);
|
||||
}, []);
|
||||
|
||||
const handleNodesChange = useCallback(
|
||||
(changes: NodeChange[]) => {
|
||||
@@ -218,6 +216,19 @@ const MapComp = ({
|
||||
}));
|
||||
}, [showKSpaceBG, isThickConnections, pings, update, localShowShipName]);
|
||||
|
||||
const prevViewport = usePrevious(defaultViewport);
|
||||
useEffect(() => {
|
||||
if (defaultViewport == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevViewport == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setViewport(defaultViewport);
|
||||
}, [defaultViewport, prevViewport, setViewport]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -232,7 +243,7 @@ const MapComp = ({
|
||||
onConnect={onConnect}
|
||||
// TODO we need save into session all of this
|
||||
// and on any action do either
|
||||
defaultViewport={getViewPortFromStore()}
|
||||
defaultViewport={defaultViewport}
|
||||
edgeTypes={edgeTypes}
|
||||
nodeTypes={nodeTypes}
|
||||
connectionMode={connectionMode}
|
||||
|
||||
@@ -11,6 +11,7 @@ export type MapData = MapUnionTypes & {
|
||||
isThickConnections: boolean;
|
||||
linkedSigEveId: string;
|
||||
localShowShipName: boolean;
|
||||
systemHighlighted: string | undefined;
|
||||
};
|
||||
|
||||
interface MapProviderProps {
|
||||
@@ -44,6 +45,7 @@ const INITIAL_DATA: MapData = {
|
||||
userHubs: [],
|
||||
pings: [],
|
||||
localShowShipName: false,
|
||||
systemHighlighted: undefined,
|
||||
};
|
||||
|
||||
export interface MapContextProps {
|
||||
|
||||
@@ -19,3 +19,14 @@
|
||||
.SelectedItem {
|
||||
background-color: var(--selected-item-bg);
|
||||
}
|
||||
|
||||
.FastActions {
|
||||
:global {
|
||||
.p-menuitem-content {
|
||||
background-color: initial !important;
|
||||
}
|
||||
.p-menuitem-content:hover {
|
||||
background-color: initial !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { ContextMenu } from 'primereact/contextmenu';
|
||||
import { MenuItem } from 'primereact/menuitem';
|
||||
import React, { RefObject, useMemo } from 'react';
|
||||
import { Edge } from 'reactflow';
|
||||
import { LifetimeActionsWrapper } from '@/hooks/Mapper/components/map/components/ContextMenuConnection/LifetimeActionsWrapper.tsx';
|
||||
import classes from './ContextMenuConnection.module.scss';
|
||||
import { getSystemStaticInfo } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
|
||||
import { isNullsecSpace } from '@/hooks/Mapper/components/map/helpers/isKnownSpace.ts';
|
||||
@@ -20,7 +21,7 @@ import { isNullsecSpace } from '@/hooks/Mapper/components/map/helpers/isKnownSpa
|
||||
export interface ContextMenuConnectionProps {
|
||||
contextMenuRef: RefObject<ContextMenu>;
|
||||
onDeleteConnection(): void;
|
||||
onChangeTimeState(): void;
|
||||
onChangeTimeState(lifetime: TimeStatus): void;
|
||||
onChangeMassState(state: MassState): void;
|
||||
onChangeShipSizeStatus(state: ShipSizeStatus): void;
|
||||
onChangeType(type: ConnectionType): void;
|
||||
@@ -80,12 +81,10 @@ export const ContextMenuConnection: React.FC<ContextMenuConnectionProps> = ({
|
||||
|
||||
return [
|
||||
{
|
||||
label: `EOL`,
|
||||
className: clsx({
|
||||
[classes.ConnectionTimeEOL]: edge.data?.time_status === TimeStatus.eol,
|
||||
}),
|
||||
icon: PrimeIcons.CLOCK,
|
||||
command: onChangeTimeState,
|
||||
className: clsx(classes.FastActions, '!h-[54px]'),
|
||||
template: () => {
|
||||
return <LifetimeActionsWrapper lifetime={edge.data?.time_status} onChangeLifetime={onChangeTimeState} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
label: `Frigate`,
|
||||
@@ -121,7 +120,6 @@ export const ContextMenuConnection: React.FC<ContextMenuConnectionProps> = ({
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
||||
{
|
||||
label: `Ship Size`,
|
||||
icon: PrimeIcons.CLOUD,
|
||||
@@ -169,7 +167,7 @@ export const ContextMenuConnection: React.FC<ContextMenuConnectionProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<ContextMenu model={items} ref={contextMenuRef} onHide={onHide} breakpoint="767px" />
|
||||
<ContextMenu model={items} ref={contextMenuRef} onHide={onHide} breakpoint="767px" className="!w-[250px]" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { LayoutEventBlocker } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { WdLifetimeSelector, WdLifetimeSelectorProps } from '@/hooks/Mapper/components/ui-kit/WdLifetimeSelector.tsx';
|
||||
|
||||
export const LifetimeActionsWrapper = (props: WdLifetimeSelectorProps) => {
|
||||
return (
|
||||
<LayoutEventBlocker className="flex flex-col gap-1 w-[100%] h-full px-2 pt-[4px]">
|
||||
<div className="text-[12px] text-stone-500 font-semibold">Life time:</div>
|
||||
|
||||
<WdLifetimeSelector {...props} />
|
||||
</LayoutEventBlocker>
|
||||
);
|
||||
};
|
||||
@@ -30,7 +30,7 @@ export const useContextMenuConnectionHandlers = () => {
|
||||
setEdge(undefined);
|
||||
};
|
||||
|
||||
const onChangeTimeState = () => {
|
||||
const onChangeTimeState = (lifetime: TimeStatus) => {
|
||||
if (!edge || !edge.data) {
|
||||
return;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ export const useContextMenuConnectionHandlers = () => {
|
||||
data: {
|
||||
source: edge.source,
|
||||
target: edge.target,
|
||||
value: edge.data.time_status === TimeStatus.default ? TimeStatus.eol : TimeStatus.default,
|
||||
value: lifetime,
|
||||
},
|
||||
});
|
||||
setEdge(undefined);
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
}
|
||||
|
||||
.hoverTarget {
|
||||
padding: 0.5rem;
|
||||
margin: -0.5rem;
|
||||
padding: 2px;
|
||||
margin: -2px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,19 @@ interface LocalCounterProps {
|
||||
localCounterCharacters: Array<CharItemProps>;
|
||||
hasUserCharacters: boolean;
|
||||
showIcon?: boolean;
|
||||
disableInteractive?: boolean;
|
||||
className?: string;
|
||||
contentClassName?: string;
|
||||
}
|
||||
|
||||
export const LocalCounter = ({ localCounterCharacters, hasUserCharacters, showIcon = true }: LocalCounterProps) => {
|
||||
export const LocalCounter = ({
|
||||
className,
|
||||
contentClassName,
|
||||
localCounterCharacters,
|
||||
hasUserCharacters,
|
||||
showIcon = true,
|
||||
disableInteractive,
|
||||
}: LocalCounterProps) => {
|
||||
const {
|
||||
data: { localShowShipName },
|
||||
} = useMapState();
|
||||
@@ -42,22 +52,30 @@ export const LocalCounter = ({ localCounterCharacters, hasUserCharacters, showIc
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(classes.TooltipActive, {
|
||||
[classes.Pathfinder]: theme === AvailableThemes.pathfinder,
|
||||
})}
|
||||
className={clsx(
|
||||
classes.TooltipActive,
|
||||
{
|
||||
[classes.Pathfinder]: theme === AvailableThemes.pathfinder,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<WdTooltipWrapper
|
||||
content={pilotTooltipContent}
|
||||
position={TooltipPosition.right}
|
||||
offset={0}
|
||||
interactive={true}
|
||||
interactive={!disableInteractive}
|
||||
smallPaddings
|
||||
>
|
||||
<div className={clsx(classes.hoverTarget)}>
|
||||
<div
|
||||
className={clsx(classes.localCounter, {
|
||||
[classes.hasUserCharacters]: hasUserCharacters,
|
||||
})}
|
||||
className={clsx(
|
||||
classes.localCounter,
|
||||
{
|
||||
[classes.hasUserCharacters]: hasUserCharacters,
|
||||
},
|
||||
contentClassName,
|
||||
)}
|
||||
>
|
||||
{showIcon && <i className="pi pi-users" />}
|
||||
<span>{localCounterCharacters.length}</span>
|
||||
|
||||
@@ -5,6 +5,16 @@
|
||||
stroke: #80a5c5;
|
||||
stroke-width: 3px;
|
||||
|
||||
&.time1 {
|
||||
stroke: #f11ab2;
|
||||
stroke-width: 4px;
|
||||
}
|
||||
|
||||
&.time4 {
|
||||
stroke: #a654e3;
|
||||
stroke-width: 4px;
|
||||
}
|
||||
|
||||
&.TimeCrit {
|
||||
stroke: #f11ab2;
|
||||
stroke-width: 4px;
|
||||
|
||||
@@ -80,7 +80,8 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }:
|
||||
id={`back_${id}`}
|
||||
className={clsx(classes.EdgePathBack, {
|
||||
[classes.Tick]: isThickConnections,
|
||||
[classes.TimeCrit]: isWormhole && data.time_status === TimeStatus.eol,
|
||||
[classes.time1]: isWormhole && data.time_status === TimeStatus._1h,
|
||||
[classes.time4]: isWormhole && data.time_status === TimeStatus._4h,
|
||||
[classes.Hovered]: hovered,
|
||||
[classes.Gate]: isGate,
|
||||
[classes.Bridge]: isBridge,
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
@use "sass:color";
|
||||
@use '@/hooks/Mapper/components/map/styles/eve-common-variables';
|
||||
|
||||
$pastel-blue: #5a7d9a;
|
||||
$pastel-pink: rgb(30, 161, 255);
|
||||
$dark-bg: #2d2d2d;
|
||||
$text-color: #ffffff;
|
||||
$tooltip-bg: #202020;
|
||||
|
||||
$neon-color-1: rgb(27, 132, 236);
|
||||
$neon-color-3: rgba(27, 132, 236, 0.40);
|
||||
@import '@/hooks/Mapper/components/map/styles/solar-system-node';
|
||||
|
||||
@keyframes move-stripes {
|
||||
from {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Handle, NodeProps, Position } from 'reactflow';
|
||||
import clsx from 'clsx';
|
||||
import classes from './SolarSystemNodeDefault.module.scss';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import { useLocalCounter, useNodeKillsCount, useSolarSystemNode } from '../../hooks';
|
||||
import { useNodeKillsCount, useSolarSystemNode } from '../../hooks';
|
||||
import {
|
||||
EFFECT_BACKGROUND_STYLES,
|
||||
MARKER_BOOKMARK_BG_STYLES,
|
||||
@@ -17,10 +17,12 @@ import { TooltipPosition, WdTooltipWrapper } from '@/hooks/Mapper/components/ui-
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { LocalCounter } from '@/hooks/Mapper/components/map/components/LocalCounter';
|
||||
import { KillsCounter } from '@/hooks/Mapper/components/map/components/KillsCounter';
|
||||
import { useLocalCounter } from '@/hooks/Mapper/components/hooks/useLocalCounter.ts';
|
||||
|
||||
// let render = 0;
|
||||
export const SolarSystemNodeDefault = memo((props: NodeProps<MapSolarSystemType>) => {
|
||||
const nodeVars = useSolarSystemNode(props);
|
||||
|
||||
const { localCounterCharacters } = useLocalCounter(nodeVars);
|
||||
const { killsCount: localKillsCount, killsActivityType: localKillsActivityType } = useNodeKillsCount(
|
||||
nodeVars.solarSystemId,
|
||||
@@ -139,12 +141,26 @@ export const SolarSystemNodeDefault = memo((props: NodeProps<MapSolarSystemType>
|
||||
|
||||
{nodeVars.isWormhole && !nodeVars.customName && <div />}
|
||||
|
||||
<div className="flex items-center gap-1 justify-end">
|
||||
<div className={clsx('flex items-center gap-1')}>
|
||||
<div className="flex items-center gap-0.5 justify-end">
|
||||
<div className={clsx('flex items-center gap-0.5')}>
|
||||
{nodeVars.locked && <i className={clsx(PrimeIcons.LOCK, classes.lockIcon)} />}
|
||||
{nodeVars.hubs.includes(nodeVars.solarSystemId) && (
|
||||
<i className={clsx(PrimeIcons.MAP_MARKER, classes.mapMarker)} />
|
||||
)}
|
||||
{nodeVars.description != null && nodeVars.description !== '' && (
|
||||
<WdTooltipWrapper
|
||||
className="h-[15px] transform -translate-y-[6%]"
|
||||
position={TooltipPosition.top}
|
||||
content={`System have description`}
|
||||
>
|
||||
<i
|
||||
className={clsx(
|
||||
'pi hero-chat-bubble-bottom-center-text w-[10px] h-[10px]',
|
||||
'text-[8px] relative top-[1px]',
|
||||
)}
|
||||
/>
|
||||
</WdTooltipWrapper>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<LocalCounter
|
||||
@@ -177,6 +193,17 @@ export const SolarSystemNodeDefault = memo((props: NodeProps<MapSolarSystemType>
|
||||
</>
|
||||
)}
|
||||
|
||||
{nodeVars.systemHighlighted === nodeVars.solarSystemId && (
|
||||
<div
|
||||
className={clsx('absolute top-[-4px] left-[-4px]', 'w-[calc(100%+8px)] h-[calc(100%+8px)]', 'animate-pulse')}
|
||||
>
|
||||
<div className="absolute left-0 top-0 w-3 h-2 border-t-2 border-l-2 border-sky-300"></div>
|
||||
<div className="absolute right-0 top-0 w-3 h-2 border-t-2 border-r-2 border-sky-300"></div>
|
||||
<div className="absolute left-0 bottom-0 w-3 h-2 border-b-2 border-l-2 border-sky-300"></div>
|
||||
<div className="absolute right-0 bottom-0 w-3 h-2 border-b-2 border-r-2 border-sky-300"></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={classes.Handlers}>
|
||||
<Handle
|
||||
type="source"
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Handle, NodeProps, Position } from 'reactflow';
|
||||
import clsx from 'clsx';
|
||||
import classes from './SolarSystemNodeTheme.module.scss';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import { useLocalCounter, useNodeKillsCount, useSolarSystemNode } from '../../hooks';
|
||||
import { useNodeKillsCount, useSolarSystemNode } from '../../hooks';
|
||||
import {
|
||||
EFFECT_BACKGROUND_STYLES,
|
||||
MARKER_BOOKMARK_BG_STYLES,
|
||||
@@ -16,6 +16,7 @@ import { TooltipPosition, WdTooltipWrapper } from '@/hooks/Mapper/components/ui-
|
||||
import { TooltipSize } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper/utils.ts';
|
||||
import { LocalCounter } from '@/hooks/Mapper/components/map/components/LocalCounter';
|
||||
import { KillsCounter } from '@/hooks/Mapper/components/map/components/KillsCounter';
|
||||
import { useLocalCounter } from '@/hooks/Mapper/components/hooks/useLocalCounter.ts';
|
||||
|
||||
// let render = 0;
|
||||
export const SolarSystemNodeTheme = memo((props: NodeProps<MapSolarSystemType>) => {
|
||||
@@ -172,6 +173,17 @@ export const SolarSystemNodeTheme = memo((props: NodeProps<MapSolarSystemType>)
|
||||
</>
|
||||
)}
|
||||
|
||||
{nodeVars.systemHighlighted === nodeVars.solarSystemId && (
|
||||
<div
|
||||
className={clsx('absolute top-[-4px] left-[-4px]', 'w-[calc(100%+8px)] h-[calc(100%+8px)]', 'animate-pulse')}
|
||||
>
|
||||
<div className="absolute left-0 top-0 w-3 h-2 border-t-2 border-l-2 border-sky-300"></div>
|
||||
<div className="absolute right-0 top-0 w-3 h-2 border-t-2 border-r-2 border-sky-300"></div>
|
||||
<div className="absolute left-0 bottom-0 w-3 h-2 border-b-2 border-l-2 border-sky-300"></div>
|
||||
<div className="absolute right-0 bottom-0 w-3 h-2 border-b-2 border-r-2 border-sky-300"></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={classes.Handlers}>
|
||||
<Handle
|
||||
type="source"
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { useReactFlow } from 'reactflow';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { CommandCenterSystem } from '@/hooks/Mapper/types';
|
||||
import { useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
|
||||
import { SYSTEM_FOCUSED_LIFETIME } from '@/hooks/Mapper/constants.ts';
|
||||
|
||||
export const useCenterSystem = () => {
|
||||
const rf = useReactFlow();
|
||||
|
||||
const ref = useRef({ rf });
|
||||
ref.current = { rf };
|
||||
const { update } = useMapState();
|
||||
|
||||
const ref = useRef({ rf, update });
|
||||
ref.current = { rf, update };
|
||||
|
||||
const highlightTimeout = useRef<number>();
|
||||
|
||||
return useCallback((systemId: CommandCenterSystem) => {
|
||||
const systemNode = ref.current.rf.getNodes().find(x => x.data.id === systemId);
|
||||
@@ -14,5 +20,16 @@ export const useCenterSystem = () => {
|
||||
return;
|
||||
}
|
||||
ref.current.rf.setCenter(systemNode.position.x, systemNode.position.y, { duration: 1000 });
|
||||
|
||||
ref.current.update({ systemHighlighted: systemId });
|
||||
|
||||
if (highlightTimeout.current !== undefined) {
|
||||
clearTimeout(highlightTimeout.current);
|
||||
}
|
||||
|
||||
highlightTimeout.current = setTimeout(() => {
|
||||
highlightTimeout.current = undefined;
|
||||
ref.current.update({ systemHighlighted: undefined });
|
||||
}, SYSTEM_FOCUSED_LIFETIME);
|
||||
}, []);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useMapGetOption } from '@/hooks/Mapper/mapRootProvider/hooks/api';
|
||||
import { useMapState } from '@/hooks/Mapper/components/map/MapProvider';
|
||||
import { useDoubleClick } from '@/hooks/Mapper/hooks/useDoubleClick';
|
||||
import { Regions, REGIONS_MAP, Spaces } from '@/hooks/Mapper/constants';
|
||||
import { Regions, REGIONS_MAP, SPACE_TO_CLASS } from '@/hooks/Mapper/constants';
|
||||
import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace';
|
||||
import { getSystemClassStyles } from '@/hooks/Mapper/components/map/helpers';
|
||||
import { sortWHClasses } from '@/hooks/Mapper/helpers';
|
||||
@@ -50,27 +50,9 @@ export interface SolarSystemNodeVars {
|
||||
isRally: boolean;
|
||||
classTitle: string | null;
|
||||
temporaryName?: string | null;
|
||||
}
|
||||
|
||||
const SpaceToClass: Record<string, string> = {
|
||||
[Spaces.Caldari]: 'Caldaria',
|
||||
[Spaces.Matar]: 'Mataria',
|
||||
[Spaces.Amarr]: 'Amarria',
|
||||
[Spaces.Gallente]: 'Gallente',
|
||||
[Spaces.Pochven]: 'Pochven',
|
||||
};
|
||||
|
||||
export function useLocalCounter(nodeVars: SolarSystemNodeVars) {
|
||||
const localCounterCharacters = useMemo(() => {
|
||||
return nodeVars.charactersInSystem
|
||||
.map(char => ({
|
||||
...char,
|
||||
compact: true,
|
||||
isOwn: nodeVars.userCharacters.includes(char.eve_id),
|
||||
}))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}, [nodeVars.charactersInSystem, nodeVars.userCharacters]);
|
||||
return { localCounterCharacters };
|
||||
description: string | null;
|
||||
comments_count: number | null;
|
||||
systemHighlighted: string | undefined;
|
||||
}
|
||||
|
||||
export const useSolarSystemNode = (props: NodeProps<MapSolarSystemType>): SolarSystemNodeVars => {
|
||||
@@ -84,6 +66,8 @@ export const useSolarSystemNode = (props: NodeProps<MapSolarSystemType>): SolarS
|
||||
labels,
|
||||
temporary_name,
|
||||
linked_sig_eve_id: linkedSigEveId = '',
|
||||
description,
|
||||
comments_count,
|
||||
} = data;
|
||||
|
||||
const {
|
||||
@@ -125,6 +109,7 @@ export const useSolarSystemNode = (props: NodeProps<MapSolarSystemType>): SolarS
|
||||
showKSpaceBG,
|
||||
isThickConnections,
|
||||
pings,
|
||||
systemHighlighted,
|
||||
},
|
||||
outCommand,
|
||||
} = useMapState();
|
||||
@@ -169,7 +154,7 @@ export const useSolarSystemNode = (props: NodeProps<MapSolarSystemType>): SolarS
|
||||
const showHandlers = isConnecting || hoverNodeId === id;
|
||||
|
||||
const space = showKSpaceBG ? REGIONS_MAP[region_id] : '';
|
||||
const regionClass = showKSpaceBG ? SpaceToClass[space] || null : null;
|
||||
const regionClass = showKSpaceBG ? SPACE_TO_CLASS[space] || null : null;
|
||||
|
||||
const { systemName, computedTemporaryName, customName } = useSystemName({
|
||||
isTempSystemNameEnabled,
|
||||
@@ -232,6 +217,9 @@ export const useSolarSystemNode = (props: NodeProps<MapSolarSystemType>): SolarS
|
||||
regionName,
|
||||
solarSystemName: solar_system_name,
|
||||
isRally,
|
||||
description,
|
||||
comments_count,
|
||||
systemHighlighted,
|
||||
};
|
||||
|
||||
return nodeVars;
|
||||
|
||||
@@ -10,3 +10,5 @@ export type OnMapSelectionChange = (event: {
|
||||
}) => void;
|
||||
|
||||
export type OnMapAddSystemCallback = (props: { coordinates: XYPosition | null }) => void;
|
||||
|
||||
export type MapViewport = { zoom: 1; x: 0; y: 0 };
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
$pastel-blue: #5a7d9a;
|
||||
$pastel-pink: rgb(30, 161, 255);
|
||||
$dark-bg: #2d2d2d;
|
||||
$text-color: #ffffff;
|
||||
$tooltip-bg: #202020;
|
||||
|
||||
$neon-color-1: rgb(27, 132, 236);
|
||||
$neon-color-3: rgba(27, 132, 236, 0.40);
|
||||
@@ -1,16 +1,15 @@
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { SystemViewStandalone, WdButton, WHClassView, WHEffectView } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { Button } from 'primereact/button';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { AutoComplete } from 'primereact/autocomplete';
|
||||
import { OutCommand, SearchSystemItem } from '@/hooks/Mapper/types';
|
||||
import { SystemViewStandalone, WHClassView, WHEffectView } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { AutoComplete } from 'primereact/autocomplete';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import classes from './AddSystemDialog.module.scss';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace.ts';
|
||||
import { sortWHClasses } from '@/hooks/Mapper/helpers';
|
||||
import clsx from 'clsx';
|
||||
|
||||
export type SearchOnSubmitCallback = (item: SearchSystemItem) => void;
|
||||
|
||||
@@ -34,6 +33,7 @@ export const AddSystemDialog = ({
|
||||
data: { wormholesData },
|
||||
} = useMapRootState();
|
||||
|
||||
// TODO fix it
|
||||
const inputRef = useRef<any>();
|
||||
const onShow = useCallback(() => {
|
||||
inputRef.current?.focus();
|
||||
@@ -62,6 +62,7 @@ export const AddSystemDialog = ({
|
||||
},
|
||||
});
|
||||
|
||||
// TODO fix it
|
||||
let prepared = (result.systems as SearchSystemItem[]).sort((a, b) => {
|
||||
const amatch = a.label.indexOf(query);
|
||||
const bmatch = b.label.indexOf(query);
|
||||
@@ -114,90 +115,93 @@ export const AddSystemDialog = ({
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col gap-3 px-1.5">
|
||||
<div className="flex flex-col gap-2 py-3.5">
|
||||
<div className="flex flex-col gap-1">
|
||||
<IconField>
|
||||
<AutoComplete
|
||||
ref={inputRef}
|
||||
multiple
|
||||
showEmptyMessage
|
||||
scrollHeight="300px"
|
||||
value={selectedItem}
|
||||
suggestions={filteredItems}
|
||||
completeMethod={searchItems}
|
||||
onChange={e => {
|
||||
setSelectedItem(e.value.length < 2 ? e.value : [e.value[e.value.length - 1]]);
|
||||
}}
|
||||
emptyMessage="Not found any system..."
|
||||
placeholder="Type here..."
|
||||
field="label"
|
||||
id="value"
|
||||
className="w-full"
|
||||
itemTemplate={(item: SearchSystemItem) => {
|
||||
const { security, system_class, effect_power, effect_name, statics } = item.system_static_info;
|
||||
const sortedStatics = sortWHClasses(wormholesData, statics);
|
||||
const isWH = isWormholeSpace(system_class);
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="flex flex-col gap-3 px-1.5">
|
||||
<div className="flex flex-col gap-2 py-3.5">
|
||||
<div className="flex flex-col gap-1">
|
||||
<IconField>
|
||||
<AutoComplete
|
||||
ref={inputRef}
|
||||
multiple
|
||||
showEmptyMessage
|
||||
scrollHeight="300px"
|
||||
value={selectedItem}
|
||||
suggestions={filteredItems}
|
||||
completeMethod={searchItems}
|
||||
onChange={e => {
|
||||
setSelectedItem(e.value.length < 2 ? e.value : [e.value[e.value.length - 1]]);
|
||||
}}
|
||||
emptyMessage="Not found any system..."
|
||||
placeholder="Type here..."
|
||||
field="label"
|
||||
id="value"
|
||||
className="w-full"
|
||||
itemTemplate={(item: SearchSystemItem) => {
|
||||
const { security, system_class, effect_power, effect_name, statics } = item.system_static_info;
|
||||
const sortedStatics = sortWHClasses(wormholesData, statics);
|
||||
const isWH = isWormholeSpace(system_class);
|
||||
|
||||
return (
|
||||
<div className={clsx('flex gap-1.5', classes.SearchItem)}>
|
||||
<SystemViewStandalone
|
||||
security={security}
|
||||
system_class={system_class}
|
||||
solar_system_id={item.value}
|
||||
class_title={item.class_title}
|
||||
solar_system_name={item.label}
|
||||
region_name={item.region_name}
|
||||
/>
|
||||
|
||||
{effect_name && isWH && (
|
||||
<WHEffectView
|
||||
effectName={effect_name}
|
||||
effectPower={effect_power}
|
||||
className={classes.SearchItemEffect}
|
||||
return (
|
||||
<div className={clsx('flex gap-1.5', classes.SearchItem)}>
|
||||
<SystemViewStandalone
|
||||
security={security}
|
||||
system_class={system_class}
|
||||
solar_system_id={item.value}
|
||||
class_title={item.class_title}
|
||||
solar_system_name={item.label}
|
||||
region_name={item.region_name}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isWH && (
|
||||
<div className="flex gap-1 grow justify-between">
|
||||
<div></div>
|
||||
<div className="flex gap-1">
|
||||
{sortedStatics.map(x => (
|
||||
<WHClassView key={x} whClassName={x} />
|
||||
))}
|
||||
{effect_name && isWH && (
|
||||
<WHEffectView
|
||||
effectName={effect_name}
|
||||
effectPower={effect_power}
|
||||
className={classes.SearchItemEffect}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isWH && (
|
||||
<div className="flex gap-1 grow justify-between">
|
||||
<div></div>
|
||||
<div className="flex gap-1">
|
||||
{sortedStatics.map(x => (
|
||||
<WHClassView key={x} whClassName={x} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
selectedItemTemplate={(item: SearchSystemItem) => (
|
||||
<SystemViewStandalone
|
||||
security={item.system_static_info.security}
|
||||
system_class={item.system_static_info.system_class}
|
||||
solar_system_id={item.value}
|
||||
class_title={item.class_title}
|
||||
solar_system_name={item.label}
|
||||
region_name={item.region_name}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</IconField>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
selectedItemTemplate={(item: SearchSystemItem) => (
|
||||
<SystemViewStandalone
|
||||
security={item.system_static_info.security}
|
||||
system_class={item.system_static_info.system_class}
|
||||
solar_system_id={item.value}
|
||||
class_title={item.class_title}
|
||||
solar_system_name={item.label}
|
||||
region_name={item.region_name}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</IconField>
|
||||
|
||||
<span className="text-[12px] text-stone-400 ml-1">*to search type at least 2 symbols.</span>
|
||||
<span className="text-[12px] text-stone-400 ml-1">*to search type at least 2 symbols.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<WdButton
|
||||
type="submit"
|
||||
onClick={handleSubmit}
|
||||
outlined
|
||||
disabled={!selectedItem || selectedItem.length !== 1}
|
||||
size="small"
|
||||
label="Submit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
outlined
|
||||
disabled={!selectedItem || selectedItem.length !== 1}
|
||||
size="small"
|
||||
label="Submit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
SystemView,
|
||||
TimeAgo,
|
||||
TooltipPosition,
|
||||
WdButton,
|
||||
WdImgButton,
|
||||
WdImgButtonTooltip,
|
||||
} from '@/hooks/Mapper/components/ui-kit';
|
||||
@@ -13,7 +14,6 @@ import { PingsPlacement } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { Commands, OutCommand, PingType } from '@/hooks/Mapper/types';
|
||||
import clsx from 'clsx';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import { Button } from 'primereact/button';
|
||||
import { ConfirmPopup } from 'primereact/confirmpopup';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
@@ -256,7 +256,7 @@ export const PingsInterface = ({ hasLeftOffset }: PingsInterfaceProps) => {
|
||||
)}
|
||||
></Toast>
|
||||
|
||||
<Button
|
||||
<WdButton
|
||||
icon="pi pi-bell"
|
||||
severity="warning"
|
||||
aria-label="Notification"
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { TooltipPosition, WdButton, WdImageSize, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { getSystemById } from '@/hooks/Mapper/helpers';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Button } from 'primereact/button';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { LabelsManager } from '@/hooks/Mapper/utils/labelsManager.ts';
|
||||
import { WdImageSize, WdImgButton, TooltipPosition } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
interface SystemCustomLabelDialog {
|
||||
systemId: string;
|
||||
@@ -126,7 +125,7 @@ export const SystemCustomLabelDialog = ({ systemId, visible, setVisible }: Syste
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button onClick={handleSave} outlined size="small" label="Save"></Button>
|
||||
<WdButton type="submit" onClick={handleSave} outlined size="small" label="Save"></WdButton>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -9,10 +9,9 @@ import {
|
||||
} from '@/hooks/Mapper/components/map/constants.ts';
|
||||
import { SystemSignaturesContent } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignaturesContent';
|
||||
import { K162_TYPES_MAP } from '@/hooks/Mapper/constants.ts';
|
||||
import { getWhSize } from '@/hooks/Mapper/helpers/getWhSize';
|
||||
import { parseSignatureCustomInfo } from '@/hooks/Mapper/helpers/parseSignatureCustomInfo';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { CommandLinkSignatureToSystem, SignatureGroup, SystemSignature, TimeStatus } from '@/hooks/Mapper/types';
|
||||
import { CommandLinkSignatureToSystem, SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { SETTINGS_KEYS, SignatureSettingsType } from '@/hooks/Mapper/constants/signatures';
|
||||
|
||||
@@ -116,14 +115,14 @@ export const SystemLinkSignatureDialog = ({ data, setVisible }: SystemLinkSignat
|
||||
);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
async (signature: SystemSignature) => {
|
||||
(signature: SystemSignature) => {
|
||||
if (!signature) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { outCommand } = ref.current;
|
||||
|
||||
await outCommand({
|
||||
outCommand({
|
||||
type: OutCommand.linkSignatureToSystem,
|
||||
data: {
|
||||
...data,
|
||||
@@ -131,32 +130,9 @@ export const SystemLinkSignatureDialog = ({ data, setVisible }: SystemLinkSignat
|
||||
},
|
||||
});
|
||||
|
||||
if (parseSignatureCustomInfo(signature.custom_info).isEOL === true) {
|
||||
await outCommand({
|
||||
type: OutCommand.updateConnectionTimeStatus,
|
||||
data: {
|
||||
source: data.solar_system_source,
|
||||
target: data.solar_system_target,
|
||||
value: TimeStatus.eol,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const whShipSize = getWhSize(wormholes, signature.type);
|
||||
if (whShipSize !== undefined && whShipSize !== null) {
|
||||
await outCommand({
|
||||
type: OutCommand.updateConnectionShipSizeType,
|
||||
data: {
|
||||
source: data.solar_system_source,
|
||||
target: data.solar_system_target,
|
||||
value: whShipSize,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
setVisible(false);
|
||||
},
|
||||
[data, setVisible, wormholes],
|
||||
[data, setVisible],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { SystemView, WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { Button } from 'primereact/button';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { PingType } from '@/hooks/Mapper/types/ping.ts';
|
||||
import { SystemView } from '@/hooks/Mapper/components/ui-kit';
|
||||
import clsx from 'clsx';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
|
||||
const PING_TITLES = {
|
||||
[PingType.Rally]: 'RALLY',
|
||||
@@ -63,7 +62,7 @@ export const SystemPingDialog = ({ systemId, type, visible, setVisible }: System
|
||||
</div>
|
||||
}
|
||||
visible={visible}
|
||||
draggable={false}
|
||||
draggable={true}
|
||||
style={{ width: '450px' }}
|
||||
onShow={onShow}
|
||||
onHide={() => {
|
||||
@@ -92,7 +91,7 @@ export const SystemPingDialog = ({ systemId, type, visible, setVisible }: System
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button onClick={handleSave} size="small" severity="danger" label="Ping!"></Button>
|
||||
<WdButton type="submit" onClick={handleSave} size="small" severity="danger" label="Ping!" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { TooltipPosition, WdButton, WdImageSize, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { getSystemById } from '@/hooks/Mapper/helpers';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useMapGetOption } from '@/hooks/Mapper/mapRootProvider/hooks/api';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Button } from 'primereact/button';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { TooltipPosition, WdImageSize, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { LabelsManager } from '@/hooks/Mapper/utils/labelsManager.ts';
|
||||
import { getSystemStaticInfo } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { LabelsManager } from '@/hooks/Mapper/utils/labelsManager.ts';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
interface SystemSettingsDialog {
|
||||
systemId: string;
|
||||
@@ -126,7 +125,7 @@ export const SystemSettingsDialog = ({ systemId, visible, setVisible }: SystemSe
|
||||
}}
|
||||
>
|
||||
<form onSubmit={handleSave}>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-col gap-3 px-2">
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex flex-col gap-1">
|
||||
<label htmlFor="username">Custom name</label>
|
||||
@@ -226,7 +225,7 @@ export const SystemSettingsDialog = ({ systemId, visible, setVisible }: SystemSe
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button onClick={handleSave} outlined size="small" label="Save"></Button>
|
||||
<WdButton onClick={handleSave} outlined size="small" label="Save" type="submit" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { useRouteProvider } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesProvider.tsx';
|
||||
import { PrettySwitchbox } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/components';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { RoutesType } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Button } from 'primereact/button';
|
||||
import {
|
||||
RoutesType,
|
||||
useRouteProvider,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesProvider.tsx';
|
||||
import { PrettySwitchbox } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/components';
|
||||
|
||||
interface RoutesSettingsDialog {
|
||||
visible: boolean;
|
||||
@@ -83,7 +81,7 @@ export const RoutesSettingsDialog = ({ visible, setVisible }: RoutesSettingsDial
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button onClick={handleSave} outlined size="small" label="Apply"></Button>
|
||||
<WdButton onClick={handleSave} outlined size="small" label="Apply"></WdButton>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Button } from 'primereact/button';
|
||||
import { TabPanel, TabView } from 'primereact/tabview';
|
||||
import { PrettySwitchbox } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/components';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
@@ -10,6 +9,7 @@ import {
|
||||
SIGNATURE_SETTINGS,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
|
||||
import { SignatureSettingsType } from '@/hooks/Mapper/constants/signatures.ts';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
interface SystemSignatureSettingsDialogProps {
|
||||
settings: SignatureSettingsType;
|
||||
@@ -92,7 +92,7 @@ export const SystemSignatureSettingsDialog = ({
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button onClick={handleSave} outlined size="small" label="Save"></Button>
|
||||
<WdButton onClick={handleSave} outlined size="small" label="Save" />
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Button } from 'primereact/button';
|
||||
import { AutoComplete } from 'primereact/autocomplete';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { StructureItem, StructureStatus, statusesRequiringTimer, formatToISO } from '../helpers';
|
||||
import { formatToISO, statusesRequiringTimer, StructureItem, StructureStatus } from '../helpers';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
interface StructuresEditDialogProps {
|
||||
visible: boolean;
|
||||
@@ -54,14 +54,13 @@ export const SystemStructuresDialog: React.FC<StructuresEditDialogProps> = ({
|
||||
|
||||
// If user typed more text but we have partial match in prevResults
|
||||
if (newQuery.startsWith(prevQuery) && prevResults.length > 0) {
|
||||
const filtered = prevResults.filter(item =>
|
||||
item.label.toLowerCase().includes(newQuery.toLowerCase()),
|
||||
);
|
||||
const filtered = prevResults.filter(item => item.label.toLowerCase().includes(newQuery.toLowerCase()));
|
||||
setOwnerSuggestions(filtered);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO fix it
|
||||
const { results = [] } = await outCommand({
|
||||
type: OutCommand.getCorporationNames,
|
||||
data: { search: newQuery },
|
||||
@@ -96,9 +95,7 @@ export const SystemStructuresDialog: React.FC<StructuresEditDialogProps> = ({
|
||||
// when user picks a corp from auto-complete
|
||||
const handleSelectOwner = (selected: { label: string; value: string }) => {
|
||||
setOwnerInput(selected.label);
|
||||
setEditData(prev =>
|
||||
prev ? { ...prev, ownerName: selected.label, ownerId: selected.value } : null,
|
||||
);
|
||||
setEditData(prev => (prev ? { ...prev, ownerName: selected.label, ownerId: selected.value } : null));
|
||||
};
|
||||
|
||||
const handleStatusChange = (val: string) => {
|
||||
@@ -125,6 +122,7 @@ export const SystemStructuresDialog: React.FC<StructuresEditDialogProps> = ({
|
||||
// fetch corporation ticker if we have an ownerId
|
||||
if (editData.ownerId) {
|
||||
try {
|
||||
// TODO fix it
|
||||
const { ticker } = await outCommand({
|
||||
type: OutCommand.getCorporationTicker,
|
||||
data: { corp_id: editData.ownerId },
|
||||
@@ -157,11 +155,7 @@ export const SystemStructuresDialog: React.FC<StructuresEditDialogProps> = ({
|
||||
<div className="flex flex-col gap-2 text-[14px]">
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center">
|
||||
<span>Type:</span>
|
||||
<input
|
||||
readOnly
|
||||
className="p-inputtext p-component cursor-not-allowed"
|
||||
value={editData.structureType ?? ''}
|
||||
/>
|
||||
<input readOnly className="p-inputtext p-component cursor-not-allowed" value={editData.structureType ?? ''} />
|
||||
</label>
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center">
|
||||
<span>Name:</span>
|
||||
@@ -204,10 +198,12 @@ export const SystemStructuresDialog: React.FC<StructuresEditDialogProps> = ({
|
||||
|
||||
{statusesRequiringTimer.includes(editData.status) && (
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center">
|
||||
<span>Timer <br /> (Eve Time):</span>
|
||||
<span>
|
||||
Timer <br /> (Eve Time):
|
||||
</span>
|
||||
<Calendar
|
||||
value={editData.endTime ? new Date(editData.endTime) : undefined}
|
||||
onChange={(e) => handleChange('endTime', e.value ?? '')}
|
||||
onChange={e => handleChange('endTime', e.value ?? '')}
|
||||
showTime
|
||||
hourFormat="24"
|
||||
dateFormat="yy-mm-dd"
|
||||
@@ -227,8 +223,8 @@ export const SystemStructuresDialog: React.FC<StructuresEditDialogProps> = ({
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end items-center gap-2 mt-4">
|
||||
<Button label="Delete" severity="danger" className="p-button-sm" onClick={handleDeleteClick} />
|
||||
<Button label="Save" className="p-button-sm" onClick={handleSaveClick} />
|
||||
<WdButton label="Delete" severity="danger" className="p-button-sm" onClick={handleDeleteClick} />
|
||||
<WdButton label="Save" className="p-button-sm" onClick={handleSaveClick} />
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Button } from 'primereact/button';
|
||||
import { WdImgButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { SystemView, TooltipPosition, WdButton, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import {
|
||||
AddSystemDialog,
|
||||
SearchOnSubmitCallback,
|
||||
} from '@/hooks/Mapper/components/mapInterface/components/AddSystemDialog';
|
||||
import { SystemView, TooltipPosition } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
interface KillsSettingsDialogProps {
|
||||
@@ -158,7 +156,7 @@ export const KillsSettingsDialog: React.FC<KillsSettingsDialogProps> = ({ visibl
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end mt-4">
|
||||
<Button onClick={handleApply} label="Apply" outlined size="small" />
|
||||
<WdButton onClick={handleApply} label="Apply" outlined size="small" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useCallback, useMemo, useState, useEffect, useRef } from 'react';
|
||||
import debounce from 'lodash.debounce';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers';
|
||||
import { DetailedKill } from '@/hooks/Mapper/types/kills';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useStableValue } from '@/hooks/Mapper/hooks';
|
||||
|
||||
interface UseSystemKillsProps {
|
||||
systemId?: string;
|
||||
@@ -30,9 +30,8 @@ export function useSystemKills({ systemId, outCommand, showAllVisible = false, s
|
||||
update,
|
||||
storedSettings: { settingsKills },
|
||||
} = useMapRootState();
|
||||
const { excludedSystems } = settingsKills;
|
||||
|
||||
const effectiveSinceHours = sinceHours;
|
||||
const excludedSystems = useStableValue(settingsKills.excludedSystems);
|
||||
|
||||
const effectiveSystemIds = useMemo(() => {
|
||||
if (showAllVisible) {
|
||||
@@ -76,13 +75,13 @@ export function useSystemKills({ systemId, outCommand, showAllVisible = false, s
|
||||
eventType = OutCommand.getSystemsKills;
|
||||
requestData = {
|
||||
system_ids: effectiveSystemIds,
|
||||
since_hours: effectiveSinceHours,
|
||||
since_hours: sinceHours,
|
||||
};
|
||||
} else if (systemId) {
|
||||
eventType = OutCommand.getSystemKills;
|
||||
requestData = {
|
||||
system_id: systemId,
|
||||
since_hours: effectiveSinceHours,
|
||||
since_hours: sinceHours,
|
||||
};
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
@@ -110,16 +109,7 @@ export function useSystemKills({ systemId, outCommand, showAllVisible = false, s
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[showAllVisible, systemId, outCommand, effectiveSystemIds, effectiveSinceHours, mergeKillsIntoGlobal],
|
||||
);
|
||||
|
||||
const debouncedFetchKills = useMemo(
|
||||
() =>
|
||||
debounce(fetchKills, 500, {
|
||||
leading: true,
|
||||
trailing: false,
|
||||
}),
|
||||
[fetchKills],
|
||||
[showAllVisible, systemId, outCommand, effectiveSystemIds, sinceHours, mergeKillsIntoGlobal],
|
||||
);
|
||||
|
||||
const finalKills = useMemo(() => {
|
||||
@@ -141,27 +131,22 @@ export function useSystemKills({ systemId, outCommand, showAllVisible = false, s
|
||||
useEffect(() => {
|
||||
if (!systemId && !showAllVisible && !didFallbackFetch.current) {
|
||||
didFallbackFetch.current = true;
|
||||
debouncedFetchKills.cancel();
|
||||
fetchKills(true);
|
||||
}
|
||||
}, [systemId, showAllVisible, debouncedFetchKills, fetchKills]);
|
||||
}, [systemId, showAllVisible, fetchKills]);
|
||||
|
||||
useEffect(() => {
|
||||
if (effectiveSystemIds.length === 0) return;
|
||||
|
||||
if (showAllVisible || systemId) {
|
||||
// Cancel any pending debounced fetch
|
||||
debouncedFetchKills.cancel();
|
||||
// Fetch kills immediately
|
||||
fetchKills();
|
||||
return () => debouncedFetchKills.cancel();
|
||||
return;
|
||||
}
|
||||
}, [showAllVisible, systemId, effectiveSystemIds, debouncedFetchKills, fetchKills]);
|
||||
}, [showAllVisible, systemId, effectiveSystemIds, fetchKills]);
|
||||
|
||||
const refetch = useCallback(() => {
|
||||
debouncedFetchKills.cancel();
|
||||
fetchKills();
|
||||
}, [debouncedFetchKills, fetchKills]);
|
||||
}, [fetchKills]);
|
||||
|
||||
return {
|
||||
kills: finalKills,
|
||||
|
||||
@@ -15,6 +15,7 @@ import { useMapEventListener } from '@/hooks/Mapper/events';
|
||||
import { Commands } from '@/hooks/Mapper/types';
|
||||
import { PingsInterface } from '@/hooks/Mapper/components/mapInterface/components';
|
||||
import { OldSettingsDialog } from '@/hooks/Mapper/components/mapRootContent/components/OldSettingsDialog.tsx';
|
||||
import { TopSearch } from '@/hooks/Mapper/components/mapRootContent/components/TopSearch';
|
||||
|
||||
export interface MapRootContentProps {}
|
||||
|
||||
@@ -72,6 +73,7 @@ export const MapRootContent = ({}: MapRootContentProps) => {
|
||||
<div className="absolute top-0 left-14 w-[calc(100%-3.5rem)] h-[calc(100%-3.5rem)] pointer-events-none">
|
||||
<Topbar>
|
||||
<div className="flex items-center ml-1">
|
||||
<TopSearch />
|
||||
<PingsInterface />
|
||||
<MapContextMenu
|
||||
onShowOnTheMap={handleShowOnTheMap}
|
||||
|
||||
@@ -62,7 +62,7 @@ export const MapSettingsComp = ({ visible, onHide }: MapSettingsProps) => {
|
||||
header="Map user settings"
|
||||
visible
|
||||
draggable={false}
|
||||
style={{ width: '600px' }}
|
||||
className="w-[600px] h-[400px]"
|
||||
onShow={handleShow}
|
||||
onHide={handleHide}
|
||||
>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { Button } from 'primereact/button';
|
||||
import { callToastError, callToastSuccess, callToastWarn } from '@/hooks/Mapper/helpers';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { ConfirmPopup } from 'primereact/confirmpopup';
|
||||
@@ -10,6 +9,7 @@ import { MapUserSettings, RemoteAdminSettingsResponse } from '@/hooks/Mapper/map
|
||||
import { parseMapUserSettings } from '@/hooks/Mapper/components/helpers';
|
||||
import fastDeepEqual from 'fast-deep-equal';
|
||||
import { useDetectSettingsChanged } from '@/hooks/Mapper/components/hooks';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
export const AdminSettings = () => {
|
||||
const {
|
||||
@@ -92,7 +92,7 @@ export const AdminSettings = () => {
|
||||
<div className="w-full h-full flex flex-col gap-5">
|
||||
<div className="flex flex-col gap-1">
|
||||
<div>
|
||||
<Button
|
||||
<WdButton
|
||||
// @ts-ignore
|
||||
ref={cfRef}
|
||||
onClick={cfShow}
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
import { useMapSettings } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/MapSettingsProvider.tsx';
|
||||
import { SettingsListItem } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/types.ts';
|
||||
import { useCallback } from 'react';
|
||||
import { Button } from 'primereact/button';
|
||||
import { TooltipPosition, WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { TooltipPosition, WdButton, WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { ConfirmPopup } from 'primereact/confirmpopup';
|
||||
import { useConfirmPopup } from '@/hooks/Mapper/hooks';
|
||||
|
||||
@@ -42,7 +41,7 @@ export const CommonSettings = () => {
|
||||
<div className="grid grid-cols-[1fr_auto]">
|
||||
<div />
|
||||
<WdTooltipWrapper content="This dangerous action. And can not be undone" position={TooltipPosition.top}>
|
||||
<Button
|
||||
<WdButton
|
||||
// @ts-ignore
|
||||
ref={cfRef}
|
||||
className="py-[4px]"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { Button } from 'primereact/button';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { Divider } from 'primereact/divider';
|
||||
import { callToastError, callToastSuccess, callToastWarn } from '@/hooks/Mapper/helpers';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
type SaveDefaultSettingsReturn = { success: boolean; error: string };
|
||||
|
||||
@@ -65,7 +65,7 @@ export const DefaultSettings = () => {
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<div>
|
||||
<Button
|
||||
<WdButton
|
||||
onClick={handleSaveAsDefault}
|
||||
icon="pi pi-save"
|
||||
size="small"
|
||||
|
||||
@@ -5,6 +5,8 @@ import { parseMapUserSettings } from '@/hooks/Mapper/components/helpers';
|
||||
import { saveTextFile } from '@/hooks/Mapper/utils/saveToFile.ts';
|
||||
import { SplitButton } from 'primereact/splitbutton';
|
||||
import { loadTextFile } from '@/hooks/Mapper/utils';
|
||||
import { applyMigrations } from '@/hooks/Mapper/mapRootProvider/migrations';
|
||||
import { createDefaultStoredSettings } from '@/hooks/Mapper/mapRootProvider/helpers/createDefaultStoredSettings.ts';
|
||||
|
||||
export const ImportExport = () => {
|
||||
const {
|
||||
@@ -22,8 +24,9 @@ export const ImportExport = () => {
|
||||
}
|
||||
|
||||
try {
|
||||
// INFO: WE NOT SUPPORT MIGRATIONS FOR OLD FILES AND Clipboard
|
||||
const parsed = parseMapUserSettings(text);
|
||||
if (applySettings(parsed)) {
|
||||
if (applySettings(applyMigrations(parsed) || createDefaultStoredSettings())) {
|
||||
toast.current?.show({
|
||||
severity: 'success',
|
||||
summary: 'Import',
|
||||
@@ -59,8 +62,9 @@ export const ImportExport = () => {
|
||||
try {
|
||||
const text = await loadTextFile();
|
||||
|
||||
// INFO: WE NOT SUPPORT MIGRATIONS FOR OLD FILES AND Clipboard
|
||||
const parsed = parseMapUserSettings(text);
|
||||
if (applySettings(parsed)) {
|
||||
if (applySettings(applyMigrations(parsed) || createDefaultStoredSettings())) {
|
||||
toast.current?.show({
|
||||
severity: 'success',
|
||||
summary: 'Import',
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { parseMapUserSettings } from '@/hooks/Mapper/components/helpers';
|
||||
import { Button } from 'primereact/button';
|
||||
import { OutCommand } from '@/hooks/Mapper/types';
|
||||
import { createDefaultWidgetSettings } from '@/hooks/Mapper/mapRootProvider/helpers/createDefaultWidgetSettings.ts';
|
||||
import { createDefaultStoredSettings } from '@/hooks/Mapper/mapRootProvider/helpers/createDefaultStoredSettings.ts';
|
||||
import { callToastSuccess } from '@/hooks/Mapper/helpers';
|
||||
import { ConfirmPopup } from 'primereact/confirmpopup';
|
||||
import { useConfirmPopup } from '@/hooks/Mapper/hooks';
|
||||
import { RemoteAdminSettingsResponse } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { applyMigrations } from '@/hooks/Mapper/mapRootProvider/migrations';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
export const ServerSettings = () => {
|
||||
const {
|
||||
@@ -29,15 +29,16 @@ export const ServerSettings = () => {
|
||||
}
|
||||
|
||||
if (res?.default_settings == null) {
|
||||
applySettings(createDefaultWidgetSettings());
|
||||
applySettings(createDefaultStoredSettings());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
applySettings(parseMapUserSettings(res.default_settings));
|
||||
//INFO: INSTEAD CHECK WE WILL TRY TO APPLY MIGRATION
|
||||
applySettings(applyMigrations(JSON.parse(res.default_settings)) || createDefaultStoredSettings());
|
||||
callToastSuccess(toast.current, 'Settings synchronized successfully');
|
||||
} catch (error) {
|
||||
applySettings(createDefaultWidgetSettings());
|
||||
applySettings(createDefaultStoredSettings());
|
||||
}
|
||||
}, [applySettings, outCommand]);
|
||||
|
||||
@@ -64,7 +65,7 @@ export const ServerSettings = () => {
|
||||
<div className="w-full h-full flex flex-col gap-5">
|
||||
<div className="flex flex-col gap-1">
|
||||
<div>
|
||||
<Button
|
||||
<WdButton
|
||||
// @ts-ignore
|
||||
ref={cfRef}
|
||||
onClick={cfShow}
|
||||
|
||||
@@ -2,8 +2,7 @@ import { PrettySwitchbox } from '@/hooks/Mapper/components/mapRootContent/compon
|
||||
import { WIDGETS_CHECKBOXES_PROPS, WidgetsIds } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { Button } from 'primereact/button';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
export interface WidgetsSettingsProps {}
|
||||
|
||||
@@ -33,7 +32,7 @@ export const WidgetsSettings = ({}: WidgetsSettingsProps) => {
|
||||
|
||||
<div className="grid grid-cols-[1fr_auto]">
|
||||
<div />
|
||||
<Button className="py-[4px]" onClick={resetWidgets} outlined size="small" label="Reset Widgets"></Button>
|
||||
<WdButton className="py-[4px]" onClick={resetWidgets} outlined size="small" label="Reset Widgets" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SettingsListItem, UserSettingsRemoteProps } from './types.ts';
|
||||
import { InterfaceStoredSettingsProps } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { AvailableThemes, MiniMapPlacement, PingsPlacement } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { SettingsListItem, UserSettingsRemoteProps } from './types.ts';
|
||||
|
||||
export const DEFAULT_REMOTE_SETTINGS = {
|
||||
[UserSettingsRemoteProps.link_signature_on_splash]: false,
|
||||
@@ -51,7 +51,7 @@ export const SIGNATURES_CHECKBOXES_PROPS: SettingsListItem[] = [
|
||||
export const CONNECTIONS_CHECKBOXES_PROPS: SettingsListItem[] = [
|
||||
{
|
||||
prop: UserSettingsRemoteProps.delete_connection_with_sigs,
|
||||
label: 'Delete connections to linked signatures',
|
||||
label: 'Delete connections with linked signatures',
|
||||
type: 'checkbox',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,27 +1,15 @@
|
||||
import { DEFAULT_SIGNATURE_SETTINGS } from '@/hooks/Mapper/constants/signatures.ts';
|
||||
import { useConfirmPopup } from '@/hooks/Mapper/hooks';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import {
|
||||
DEFAULT_KILLS_WIDGET_SETTINGS,
|
||||
DEFAULT_ON_THE_MAP_SETTINGS,
|
||||
DEFAULT_ROUTES_SETTINGS,
|
||||
DEFAULT_WIDGET_LOCAL_SETTINGS,
|
||||
getDefaultWidgetProps,
|
||||
STORED_INTERFACE_DEFAULT_VALUES,
|
||||
} from '@/hooks/Mapper/mapRootProvider/constants.ts';
|
||||
import { MapUserSettings } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { saveTextFile } from '@/hooks/Mapper/utils';
|
||||
import { Button } from 'primereact/button';
|
||||
import { ConfirmPopup } from 'primereact/confirmpopup';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
const createSettings = function <T>(lsSettings: string | null, defaultValues: T) {
|
||||
return {
|
||||
version: -1,
|
||||
settings: lsSettings ? JSON.parse(lsSettings) : defaultValues,
|
||||
};
|
||||
return lsSettings ? JSON.parse(lsSettings) : defaultValues;
|
||||
};
|
||||
|
||||
export const OldSettingsDialog = () => {
|
||||
@@ -44,13 +32,15 @@ export const OldSettingsDialog = () => {
|
||||
const signatures = localStorage.getItem('wanderer_system_signature_settings_v6_6');
|
||||
|
||||
const out: MapUserSettings = {
|
||||
killsWidget: createSettings(widgetKills, DEFAULT_KILLS_WIDGET_SETTINGS),
|
||||
localWidget: createSettings(widgetLocal, DEFAULT_WIDGET_LOCAL_SETTINGS),
|
||||
widgets: createSettings(widgetsOld, getDefaultWidgetProps()),
|
||||
routes: createSettings(widgetRoutes, DEFAULT_ROUTES_SETTINGS),
|
||||
onTheMap: createSettings(onTheMapOld, DEFAULT_ON_THE_MAP_SETTINGS),
|
||||
signaturesWidget: createSettings(signatures, DEFAULT_SIGNATURE_SETTINGS),
|
||||
interface: createSettings(interfaceSettings, STORED_INTERFACE_DEFAULT_VALUES),
|
||||
version: 0,
|
||||
migratedFromOld: false,
|
||||
killsWidget: createSettings(widgetKills, {}),
|
||||
localWidget: createSettings(widgetLocal, {}),
|
||||
widgets: createSettings(widgetsOld, {}),
|
||||
routes: createSettings(widgetRoutes, {}),
|
||||
onTheMap: createSettings(onTheMapOld, {}),
|
||||
signaturesWidget: createSettings(signatures, {}),
|
||||
interface: createSettings(interfaceSettings, {}),
|
||||
};
|
||||
|
||||
if (asFile) {
|
||||
@@ -139,7 +129,7 @@ export const OldSettingsDialog = () => {
|
||||
className="w-[640px] h-[400px] text-text-color min-h-0"
|
||||
footer={
|
||||
<div className="flex items-center justify-end">
|
||||
<Button
|
||||
<WdButton
|
||||
// @ts-ignore
|
||||
ref={cfRef}
|
||||
onClick={cfShow}
|
||||
@@ -168,7 +158,7 @@ export const OldSettingsDialog = () => {
|
||||
<div className="h-[30px]"></div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<Button
|
||||
<WdButton
|
||||
onClick={handleExportClipboard}
|
||||
icon="pi pi-copy"
|
||||
size="small"
|
||||
@@ -176,7 +166,7 @@ export const OldSettingsDialog = () => {
|
||||
label="Export to Clipboard"
|
||||
/>
|
||||
|
||||
<Button
|
||||
<WdButton
|
||||
onClick={handleExportAsFile}
|
||||
icon="pi pi-download"
|
||||
size="small"
|
||||
|
||||
@@ -7,6 +7,7 @@ import { TooltipPosition } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
import { useMapCheckPermissions } from '@/hooks/Mapper/mapRootProvider/hooks/api';
|
||||
import { UserPermission } from '@/hooks/Mapper/types/permissions.ts';
|
||||
import { TopSearch } from '@/hooks/Mapper/components/mapRootContent/components/TopSearch';
|
||||
// import { DebugComponent } from '@/hooks/Mapper/components/mapRootContent/components/RightBar/DebugComponent.tsx';
|
||||
|
||||
interface RightBarProps {
|
||||
@@ -48,7 +49,7 @@ export const RightBar = ({
|
||||
classes.RightBarRoot,
|
||||
'w-full h-full',
|
||||
'text-gray-200 shadow-lg border-l border-zinc-800 border-opacity-70 bg-opacity-70 bg-neutral-900',
|
||||
'flex flex-col items-center justify-between',
|
||||
'flex flex-col items-center justify-between pt-1',
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col gap-2 items-center mt-1">
|
||||
@@ -65,15 +66,31 @@ export const RightBar = ({
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
|
||||
<WdTooltipWrapper content="Show on the map" position={TooltipPosition.left}>
|
||||
<button
|
||||
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent py-2 h-auto min-h-auto"
|
||||
type="button"
|
||||
onClick={onShowOnTheMap}
|
||||
>
|
||||
<i className="pi pi-hashtag"></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
<div className="flex flex-col gap-1">
|
||||
<TopSearch
|
||||
customBtn={open => (
|
||||
<WdTooltipWrapper content="Show on the map" position={TooltipPosition.left}>
|
||||
<button
|
||||
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent py-2 h-auto min-h-auto"
|
||||
type="button"
|
||||
onClick={open}
|
||||
>
|
||||
<i className="pi pi-search"></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
)}
|
||||
/>
|
||||
|
||||
<WdTooltipWrapper content="Show on the map" position={TooltipPosition.left}>
|
||||
<button
|
||||
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent py-2 h-auto min-h-auto"
|
||||
type="button"
|
||||
onClick={onShowOnTheMap}
|
||||
>
|
||||
<i className="pi pi-hashtag"></i>
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{additionalContent}
|
||||
|
||||
@@ -8,11 +8,14 @@ import {
|
||||
} from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { SystemsSettingsProvider } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/Provider.tsx';
|
||||
import { Button } from 'primereact/button';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { getWhSize } from '@/hooks/Mapper/helpers/getWhSize';
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
type SystemSignaturePrepared = Omit<SystemSignature, 'linked_system'> & { linked_system: string };
|
||||
type SystemSignaturePrepared = Omit<SystemSignature, 'linked_system'> & {
|
||||
linked_system: string;
|
||||
k162Type: string;
|
||||
time_status: TimeStatus;
|
||||
};
|
||||
|
||||
export interface MapSettingsProps {
|
||||
systemId: string;
|
||||
@@ -22,10 +25,7 @@ export interface MapSettingsProps {
|
||||
}
|
||||
|
||||
export const SignatureSettings = ({ systemId, show, onHide, signatureData }: MapSettingsProps) => {
|
||||
const {
|
||||
outCommand,
|
||||
data: { wormholes },
|
||||
} = useMapRootState();
|
||||
const { outCommand } = useMapRootState();
|
||||
|
||||
const handleShow = async () => {};
|
||||
const signatureForm = useForm<Partial<SystemSignaturePrepared>>({});
|
||||
@@ -52,41 +52,13 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
|
||||
solar_system_target: values.linked_system,
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: need fix
|
||||
if (values.isEOL) {
|
||||
await outCommand({
|
||||
type: OutCommand.updateConnectionTimeStatus,
|
||||
data: {
|
||||
source: systemId,
|
||||
target: values.linked_system,
|
||||
value: TimeStatus.eol,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (values.type) {
|
||||
const whShipSize = getWhSize(wormholes, values.type);
|
||||
if (whShipSize !== undefined && whShipSize !== null) {
|
||||
await outCommand({
|
||||
type: OutCommand.updateConnectionShipSizeType,
|
||||
data: {
|
||||
source: systemId,
|
||||
target: values.linked_system,
|
||||
value: whShipSize,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out = {
|
||||
...out,
|
||||
custom_info: JSON.stringify({
|
||||
// TODO: need fix
|
||||
k162Type: values.k162Type,
|
||||
// TODO: need fix
|
||||
isEOL: values.isEOL,
|
||||
time_status: values.time_status,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -153,7 +125,7 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
|
||||
signatureForm.reset();
|
||||
onHide();
|
||||
},
|
||||
[signatureData, signatureForm, outCommand, systemId, onHide, wormholes],
|
||||
[signatureData, signatureForm, outCommand, systemId, onHide],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -165,18 +137,17 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
|
||||
const { linked_system, custom_info, ...rest } = signatureData;
|
||||
|
||||
let k162Type = null;
|
||||
let isEOL = false;
|
||||
let time_status = TimeStatus._24h;
|
||||
if (custom_info) {
|
||||
const customInfo = JSON.parse(custom_info);
|
||||
k162Type = customInfo.k162Type;
|
||||
isEOL = customInfo.isEOL;
|
||||
time_status = customInfo.time_status;
|
||||
}
|
||||
|
||||
signatureForm.reset({
|
||||
linked_system: linked_system?.solar_system_id.toString() ?? undefined,
|
||||
// TODO: need fix
|
||||
k162Type: k162Type,
|
||||
isEOL: isEOL,
|
||||
time_status: time_status,
|
||||
...rest,
|
||||
});
|
||||
}, [signatureForm, signatureData]);
|
||||
@@ -185,7 +156,8 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
|
||||
<Dialog
|
||||
header={`Signature Edit [${signatureData?.eve_id}]`}
|
||||
visible={show}
|
||||
draggable={true}
|
||||
draggable
|
||||
resizable={false}
|
||||
style={{ width: '390px' }}
|
||||
onShow={handleShow}
|
||||
onHide={() => {
|
||||
@@ -220,8 +192,8 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button onClick={handleSave} outlined size="small" label="Save"></Button>
|
||||
<div className="flex gap-2 justify-end px-[0.75rem] pb-[0.5rem]">
|
||||
<WdButton type="submit" outlined size="small" label="Save" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { InputSwitch } from 'primereact/inputswitch';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
|
||||
export interface SignatureEOLCheckboxProps {
|
||||
name: string;
|
||||
defaultValue?: boolean;
|
||||
}
|
||||
|
||||
export const SignatureEOLCheckbox = ({ name, defaultValue = false }: SignatureEOLCheckboxProps) => {
|
||||
const { control } = useFormContext<SystemSignature>();
|
||||
|
||||
return (
|
||||
<Controller
|
||||
// @ts-ignore
|
||||
name={name}
|
||||
control={control}
|
||||
defaultValue={defaultValue}
|
||||
render={({ field }) => {
|
||||
return <InputSwitch className="my-1" checked={!!field.value} onChange={e => field.onChange(e.value)} />;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './SignatureEOLCheckbox.tsx';
|
||||
@@ -3,7 +3,7 @@ import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { SignatureWormholeTypeSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureWormholeTypeSelect';
|
||||
import { SignatureK162TypeSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureK162TypeSelect';
|
||||
import { SignatureLeadsToSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureLeadsToSelect';
|
||||
import { SignatureEOLCheckbox } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureEOLCheckbox';
|
||||
import { SignatureLifetimeSelect } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureLifetimeSelect.tsx';
|
||||
import { SignatureTempName } from '@/hooks/Mapper/components/mapRootContent/components/SignatureSettings/components/SignatureTempName.tsx';
|
||||
|
||||
export const SignatureGroupContentWormholes = () => {
|
||||
@@ -29,10 +29,10 @@ export const SignatureGroupContentWormholes = () => {
|
||||
<SignatureLeadsToSelect name="linked_system" />
|
||||
</label>
|
||||
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
|
||||
<span>EOL:</span>
|
||||
<SignatureEOLCheckbox name="isEOL" />
|
||||
</label>
|
||||
<div className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
|
||||
<span>Lifetime:</span>
|
||||
<SignatureLifetimeSelect name="time_status" />
|
||||
</div>
|
||||
|
||||
<label className="grid grid-cols-[100px_250px_1fr] gap-2 items-center text-[14px]">
|
||||
<span>Temp. Name:</span>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { WdLifetimeSelector } from '@/hooks/Mapper/components/ui-kit/WdLifetimeSelector.tsx';
|
||||
|
||||
export interface SignatureEOLCheckboxProps {
|
||||
name: string;
|
||||
defaultValue?: boolean;
|
||||
}
|
||||
|
||||
export const SignatureLifetimeSelect = ({ name, defaultValue = false }: SignatureEOLCheckboxProps) => {
|
||||
const { control } = useFormContext<SystemSignature>();
|
||||
|
||||
return (
|
||||
<div className="my-1">
|
||||
<Controller
|
||||
// @ts-ignore
|
||||
name={name}
|
||||
control={control}
|
||||
defaultValue={defaultValue}
|
||||
render={({ field }) => {
|
||||
// @ts-ignore
|
||||
return <WdLifetimeSelector lifetime={field.value} onChangeLifetime={e => field.onChange(e)} />;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './SignatureGroupSelect';
|
||||
export * from './SignatureGroupContent';
|
||||
export * from './SignatureK162TypeSelect';
|
||||
export * from './SignatureLifetimeSelect';
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
@use "sass:color";
|
||||
@use '@/hooks/Mapper/components/map/styles/eve-common-variables';
|
||||
@import '@/hooks/Mapper/components/map/styles/solar-system-node';
|
||||
|
||||
:root {
|
||||
--rf-has-user-characters: #ffc75d;
|
||||
}
|
||||
|
||||
.Sidebar {
|
||||
:global {
|
||||
.p-sidebar-header {
|
||||
padding-left: 14px;
|
||||
padding-right: 14px;
|
||||
}
|
||||
|
||||
.p-sidebar-content {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Content {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&.Pochven,
|
||||
&.Mataria,
|
||||
&.Amarria,
|
||||
&.Gallente,
|
||||
&.Caldaria {
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-size: cover;
|
||||
background-position: 50% 50%;
|
||||
z-index: -1;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&.Mataria {
|
||||
&::after {
|
||||
background-image: url('/images/mataria-180.png');
|
||||
opacity: 0.6;
|
||||
//background-position-x: 52px;
|
||||
//background-position-y: -83px;
|
||||
background-position-x: 331px;
|
||||
background-position-y: -77px;
|
||||
transform: scale(-1);
|
||||
}
|
||||
}
|
||||
|
||||
&.Caldaria {
|
||||
&::after {
|
||||
background-image: url('/images/caldaria-180.png');
|
||||
opacity: 0.6;
|
||||
//background-position-x: 41px;
|
||||
//background-position-y: -45px;
|
||||
|
||||
background-position-x: 360px;
|
||||
background-position-y: -16px;
|
||||
background-size: 30%;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
&.Amarria {
|
||||
&::after {
|
||||
opacity: 0.45;
|
||||
background-image: url('/images/amarr-small.png');
|
||||
//background-position-x: 23px;
|
||||
//background-position-y: -74px;
|
||||
|
||||
background-position-x: -1px;
|
||||
background-position-y: -75px;
|
||||
background-origin: border-box;
|
||||
background-size: auto;
|
||||
transform: scale(1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
&.Gallente {
|
||||
&::after {
|
||||
opacity: 0.5;
|
||||
background-image: url('/images/gallente-180.png');
|
||||
//background-position-x: 1px;
|
||||
//background-position-y: -55px;
|
||||
|
||||
background-position-x: 294px;
|
||||
background-position-y: -53px;
|
||||
transform: scale(-1);
|
||||
}
|
||||
}
|
||||
|
||||
&.Pochven {
|
||||
&::after {
|
||||
opacity: 0.8;
|
||||
background-image: url('/images/pochven.webp');
|
||||
background-position-x: 0;
|
||||
background-position-y: -88px;
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border-color: $pastel-pink;
|
||||
box-shadow: 0 0 10px #9a1af1c2;
|
||||
}
|
||||
|
||||
&.rally {
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
|
||||
border-color: $neon-color-1;
|
||||
background: repeating-linear-gradient(
|
||||
45deg,
|
||||
$neon-color-3 0px,
|
||||
$neon-color-3 8px,
|
||||
transparent 8px,
|
||||
transparent 21px
|
||||
);
|
||||
background-size: 30px 30px;
|
||||
animation: move-stripes 3s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
&.eve-system-status-home {
|
||||
background-image: linear-gradient(45deg, var(--eve-solar-system-status-color-background), transparent);
|
||||
&.selected {
|
||||
border-color: var(--eve-solar-system-status-color-home);
|
||||
}
|
||||
}
|
||||
|
||||
&.eve-system-status-friendly {
|
||||
background-image: linear-gradient(275deg, var(--eve-solar-system-status-friendly-dark30), transparent);
|
||||
&.selected {
|
||||
border-color: var(--eve-solar-system-status-color-friendly-dark5);
|
||||
}
|
||||
}
|
||||
|
||||
&.eve-system-status-lookingFor {
|
||||
background-image: linear-gradient(275deg, #45ff8f2f, #457fff2f);
|
||||
&.selected {
|
||||
border-color: $pastel-pink;
|
||||
}
|
||||
}
|
||||
|
||||
&.eve-system-status-warning {
|
||||
background-image: linear-gradient(275deg, var(--eve-solar-system-status-warning), transparent);
|
||||
}
|
||||
|
||||
&.eve-system-status-dangerous {
|
||||
background-image: linear-gradient(275deg, var(--eve-solar-system-status-dangerous), transparent);
|
||||
}
|
||||
|
||||
&.eve-system-status-target {
|
||||
background-image: linear-gradient(275deg, var(--eve-solar-system-status-target), transparent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
import classes from './TopSearch.module.scss';
|
||||
import { Sidebar } from 'primereact/sidebar';
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { VirtualScroller, VirtualScrollerTemplateOptions } from 'primereact/virtualscroller';
|
||||
import clsx from 'clsx';
|
||||
import { Commands, SolarSystemRawType, SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types';
|
||||
import {
|
||||
SystemViewStandalone,
|
||||
TooltipPosition,
|
||||
WdImageSize,
|
||||
WdImgButton,
|
||||
WdTooltipWrapper,
|
||||
WHClassView,
|
||||
WHEffectView,
|
||||
} from '@/hooks/Mapper/components/ui-kit';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { IconField } from 'primereact/iconfield';
|
||||
import { getSystemStaticInfo } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
|
||||
import { sortWHClasses } from '@/hooks/Mapper/helpers';
|
||||
import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace.ts';
|
||||
import { STATUS_CLASSES } from '@/hooks/Mapper/components/map/constants.ts';
|
||||
import { REGIONS_MAP, SPACE_TO_CLASS } from '@/hooks/Mapper/constants.ts';
|
||||
import { emitMapEvent } from '@/hooks/Mapper/events';
|
||||
import { LocalCounter } from '@/hooks/Mapper/components/map/components/LocalCounter';
|
||||
import { getLocalCharacters } from '@/hooks/Mapper/components/hooks/useLocalCounter.ts';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
|
||||
type CompiledSystem = {
|
||||
dynamic: SolarSystemRawType;
|
||||
static: SolarSystemStaticInfoRaw | undefined;
|
||||
};
|
||||
|
||||
const useItemTemplate = () => {
|
||||
const {
|
||||
data: { wormholesData, characters, userCharacters, hubs },
|
||||
} = useMapRootState();
|
||||
|
||||
return useCallback(
|
||||
(item: CompiledSystem, options: VirtualScrollerTemplateOptions) => {
|
||||
if (!item.static) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
security,
|
||||
system_class,
|
||||
class_title,
|
||||
effect_power,
|
||||
region_name,
|
||||
solar_system_name,
|
||||
solar_system_id,
|
||||
effect_name,
|
||||
statics,
|
||||
region_id,
|
||||
} = item.static;
|
||||
|
||||
const onlineCharactersInSystem = characters.filter(
|
||||
c => c.location?.solar_system_id === solar_system_id && c.online,
|
||||
);
|
||||
const hasOnlineUserCharacters = onlineCharactersInSystem.some(x => userCharacters.includes(x.eve_id));
|
||||
const onlineCharacters = getLocalCharacters({ charactersInSystem: onlineCharactersInSystem, userCharacters });
|
||||
|
||||
const offlineCharactersInSystem = characters.filter(
|
||||
c => c.location?.solar_system_id === solar_system_id && !c.online,
|
||||
);
|
||||
const hasOfflineUserCharacters = offlineCharactersInSystem.some(x => userCharacters.includes(x.eve_id));
|
||||
const offlineCharacters = getLocalCharacters({ charactersInSystem: offlineCharactersInSystem, userCharacters });
|
||||
|
||||
const handleSelect = () => {
|
||||
emitMapEvent({
|
||||
name: Commands.centerSystem,
|
||||
data: solar_system_id.toString(),
|
||||
});
|
||||
};
|
||||
|
||||
const sortedStatics = sortWHClasses(wormholesData, statics);
|
||||
const isWH = isWormholeSpace(system_class);
|
||||
|
||||
const regionClass = SPACE_TO_CLASS[REGIONS_MAP[region_id]] || null;
|
||||
const showTempName = item.dynamic.temporary_name != null;
|
||||
const showCustomName = item.dynamic.name != null && item.dynamic.name !== solar_system_name;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'w-full box-border px-3.5 py-1 h-[48px] cursor-pointer',
|
||||
'bg-transparent hover:bg-stone-800/30 transition-all !duration-250 ease-in-out',
|
||||
{
|
||||
'surface-hover': options.odd,
|
||||
['border-b border-gray-600 border-opacity-20']: !options.last,
|
||||
},
|
||||
classes.Content,
|
||||
regionClass && classes[regionClass],
|
||||
item.dynamic.status !== undefined && classes[STATUS_CLASSES[item.dynamic.status]],
|
||||
)}
|
||||
onClick={handleSelect}
|
||||
>
|
||||
<div className={clsx('w-full')}>
|
||||
<div className={clsx('grid grid-cols-[1fr_auto] gap-1.5 w-full')}>
|
||||
<div className="flex [&>*]:!text-[13px] gap-1.5">
|
||||
<SystemViewStandalone
|
||||
className="!text-[13px]"
|
||||
security={security}
|
||||
system_class={system_class}
|
||||
solar_system_id={parseInt(item.dynamic.id)}
|
||||
class_title={class_title}
|
||||
solar_system_name={`${solar_system_name}`}
|
||||
region_name={region_name}
|
||||
nameClassName="font-semibold"
|
||||
/>
|
||||
|
||||
{(showTempName || showCustomName) && (
|
||||
<div className="grid grid-cols-[auto_1fr] gap-1.5 text-stone-400 text-[12px]">
|
||||
{showTempName && (
|
||||
<span className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
{item.dynamic.temporary_name}
|
||||
</span>
|
||||
)}
|
||||
{showCustomName && (
|
||||
<span className="overflow-hidden text-ellipsis whitespace-nowrap">{item.dynamic.name}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{effect_name && isWH && (
|
||||
<WHEffectView
|
||||
effectName={effect_name}
|
||||
effectPower={effect_power}
|
||||
className={classes.SearchItemEffect}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{isWH && (
|
||||
<div className="flex gap-1 grow justify-between !text-[13px]">
|
||||
<div></div>
|
||||
<div className="flex gap-1">
|
||||
{sortedStatics.map(x => (
|
||||
<WHClassView key={x} whClassName={x} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-1.5 text-[13px] pl-[2px] items-center h-[20px]">
|
||||
<LocalCounter
|
||||
disableInteractive
|
||||
className="[&_span]:!text-[12px] [&_i]:!text-[13px]"
|
||||
hasUserCharacters={hasOnlineUserCharacters}
|
||||
localCounterCharacters={onlineCharacters}
|
||||
/>
|
||||
<LocalCounter
|
||||
disableInteractive
|
||||
className="[&_span]:!text-[12px] [&_i]:!text-[13px] text-stone-[400]"
|
||||
contentClassName={clsx('!text-stone-500', { ['!text-yellow-600']: hasOfflineUserCharacters })}
|
||||
hasUserCharacters={hasOfflineUserCharacters}
|
||||
localCounterCharacters={offlineCharacters}
|
||||
/>
|
||||
{item.dynamic.locked && <i className={clsx(PrimeIcons.LOCK, 'text-[11px] relative top-[1px]')} />}
|
||||
{hubs.includes(solar_system_id.toString()) && (
|
||||
<i className={clsx(PrimeIcons.MAP_MARKER, 'text-[11px] relative top-[1px]')} />
|
||||
)}
|
||||
{item.dynamic.comments_count != null && item.dynamic.comments_count > 0 && (
|
||||
<WdTooltipWrapper
|
||||
position={TooltipPosition.top}
|
||||
content={`[${item.dynamic.comments_count}] Comments in System - click to system to see it in Comments Widget`}
|
||||
>
|
||||
<i className={clsx(PrimeIcons.COMMENT, 'text-[11px] relative top-[1px]')} />
|
||||
</WdTooltipWrapper>
|
||||
)}
|
||||
{item.dynamic.description != null && item.dynamic.description !== '' && (
|
||||
<WdTooltipWrapper
|
||||
position={TooltipPosition.top}
|
||||
content={`System have description - click to system to see it in Info Widget`}
|
||||
>
|
||||
<i
|
||||
className={clsx(
|
||||
'pi hero-chat-bubble-bottom-center-text w-[14px] h-[14px]',
|
||||
'text-[8px] relative top-[-1px]',
|
||||
)}
|
||||
/>
|
||||
</WdTooltipWrapper>
|
||||
)}
|
||||
{/*kek*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
[characters, hubs, userCharacters, wormholesData],
|
||||
);
|
||||
};
|
||||
|
||||
export interface TopSearchSidebarProps {
|
||||
show: boolean;
|
||||
onHide: () => void;
|
||||
}
|
||||
|
||||
export const TopSearchSidebar = ({ show, onHide }: TopSearchSidebarProps) => {
|
||||
const [searchVal, setSearchVal] = useState('');
|
||||
|
||||
// eslint-disable-next-line
|
||||
const inputRef = useRef<any>();
|
||||
|
||||
const {
|
||||
data: { systems },
|
||||
} = useMapRootState();
|
||||
|
||||
const itemTemplate = useItemTemplate();
|
||||
|
||||
const systemsCompiled = useMemo<CompiledSystem[]>(() => {
|
||||
return systems.map(x => ({
|
||||
dynamic: x,
|
||||
static: getSystemStaticInfo(x.id),
|
||||
}));
|
||||
}, [systems]);
|
||||
|
||||
const onShow = useCallback(() => {
|
||||
inputRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
let out = systemsCompiled;
|
||||
|
||||
out = out.sort((a, b) => {
|
||||
// 1. Status > 0 — always on top and ASC
|
||||
if (a.dynamic.status > 0 && b.dynamic.status > 0) return a.dynamic.status - b.dynamic.status;
|
||||
if (a.dynamic.status > 0) return -1;
|
||||
if (b.dynamic.status > 0) return 1;
|
||||
|
||||
// 2. IF status = 0, J priority
|
||||
const aStartsWithJ = a.dynamic.name?.startsWith('J') ?? false;
|
||||
const bStartsWithJ = b.dynamic.name?.startsWith('J') ?? false;
|
||||
|
||||
if (aStartsWithJ && !bStartsWithJ) return -1;
|
||||
if (!aStartsWithJ && bStartsWithJ) return 1;
|
||||
|
||||
// 3. IF both starts with J or not - sort by name
|
||||
const nameA = a.dynamic.name ?? '';
|
||||
const nameB = b.dynamic.name ?? '';
|
||||
return nameA.localeCompare(nameB);
|
||||
});
|
||||
|
||||
const normalized = searchVal.toLowerCase();
|
||||
|
||||
if (searchVal !== '') {
|
||||
out = out.filter(x => {
|
||||
if (x.static?.solar_system_name.toLowerCase().includes(normalized)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (x.dynamic.name?.toLowerCase().includes(normalized)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (x.dynamic.temporary_name?.toLowerCase().includes(normalized)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
return out;
|
||||
}, [searchVal, systemsCompiled]);
|
||||
|
||||
return (
|
||||
<Sidebar
|
||||
className={clsx(classes.Sidebar, 'bg-neutral-900 !p-[0px] w-[500px]')}
|
||||
visible={show}
|
||||
position="right"
|
||||
onShow={onShow}
|
||||
onHide={onHide}
|
||||
modal={false}
|
||||
header={`Search [${filtered.length}]`}
|
||||
icons={<></>}
|
||||
>
|
||||
<div className={clsx('grid grid-rows-[auto_1fr] gap-y-[8px] h-full')}>
|
||||
<div className={'flex justify-between items-center gap-2 px-2 pt-1'}>
|
||||
<IconField className="w-full">
|
||||
{searchVal.length > 0 && (
|
||||
<WdImgButton
|
||||
className="pi pi-trash"
|
||||
textSize={WdImageSize.large}
|
||||
tooltip={{
|
||||
content: 'Clear',
|
||||
className: 'pi p-input-icon',
|
||||
position: TooltipPosition.top,
|
||||
}}
|
||||
onClick={() => setSearchVal('')}
|
||||
/>
|
||||
)}
|
||||
<InputText
|
||||
id="label"
|
||||
className="w-full"
|
||||
aria-describedby="label"
|
||||
ref={inputRef}
|
||||
autoComplete="off"
|
||||
value={searchVal}
|
||||
placeholder="Type To Search"
|
||||
onChange={e => setSearchVal(e.target.value)}
|
||||
/>
|
||||
</IconField>
|
||||
</div>
|
||||
|
||||
<VirtualScroller
|
||||
items={filtered}
|
||||
itemSize={48}
|
||||
itemTemplate={itemTemplate}
|
||||
className={clsx(
|
||||
classes.VirtualScroller,
|
||||
'w-full h-full overflow-x-hidden overflow-y-auto custom-scrollbar select-none',
|
||||
'[&>div]:w-full',
|
||||
)}
|
||||
autoSize={false}
|
||||
/>
|
||||
</div>
|
||||
</Sidebar>
|
||||
);
|
||||
};
|
||||
|
||||
interface TopSearchProps {
|
||||
customBtn?: (open: () => void) => React.ReactNode;
|
||||
}
|
||||
|
||||
export const TopSearch = ({ customBtn }: TopSearchProps) => {
|
||||
const [openAddSystem, setOpenAddSystem] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
{customBtn != null && customBtn(() => setOpenAddSystem(true))}
|
||||
{customBtn == null && (
|
||||
<button
|
||||
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent px-2 relative left-1"
|
||||
type="button"
|
||||
onClick={() => setOpenAddSystem(true)}
|
||||
>
|
||||
<i className="pi pi-search text-lg"></i>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<TopSearchSidebar show={openAddSystem} onHide={() => setOpenAddSystem(false)} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './TopSearch.tsx';
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Column } from 'primereact/column';
|
||||
import { CharacterCard } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { TrackingCharacter } from '@/hooks/Mapper/types';
|
||||
import { useTracking } from '@/hooks/Mapper/components/mapRootContent/components/TrackingDialog/TrackingProvider.tsx';
|
||||
|
||||
export const TrackingCharactersList = () => {
|
||||
const [selected, setSelected] = useState<TrackingCharacter[]>([]);
|
||||
const { trackingCharacters, updateTracking } = useTracking();
|
||||
const { trackingCharacters, main, following, updateTracking } = useTracking();
|
||||
const refVars = useRef({ trackingCharacters });
|
||||
refVars.current = { trackingCharacters };
|
||||
|
||||
@@ -20,9 +20,31 @@ export const TrackingCharactersList = () => {
|
||||
[updateTracking],
|
||||
);
|
||||
|
||||
const items = useMemo(() => {
|
||||
let out = trackingCharacters;
|
||||
|
||||
out = out.sort((a, b) => {
|
||||
const aId = a.character.eve_id;
|
||||
const bId = b.character.eve_id;
|
||||
|
||||
// 1. main always first
|
||||
if (aId === main && bId !== main) return -1;
|
||||
if (bId === main && aId !== main) return 1;
|
||||
|
||||
// 2. following after main
|
||||
if (aId === following && bId !== following) return -1;
|
||||
if (bId === following && aId !== following) return 1;
|
||||
|
||||
// 3. sort by name
|
||||
return a.character.name.localeCompare(b.character.name);
|
||||
});
|
||||
|
||||
return out;
|
||||
}, [trackingCharacters, main, following]);
|
||||
|
||||
return (
|
||||
<DataTable
|
||||
value={trackingCharacters}
|
||||
value={items}
|
||||
size="small"
|
||||
selectionMode={null}
|
||||
selection={selected}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Connections } from '@/hooks/Mapper/components/mapRootContent/components
|
||||
import { ContextMenuSystemMultiple, useContextMenuSystemMultipleHandlers } from '../contexts/ContextMenuSystemMultiple';
|
||||
import { getSystemById } from '@/hooks/Mapper/helpers';
|
||||
import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { Node, useReactFlow, XYPosition } from 'reactflow';
|
||||
import { Node, useReactFlow, Viewport, XYPosition } from 'reactflow';
|
||||
|
||||
import { useCommandsSystems } from '@/hooks/Mapper/mapRootProvider/hooks/api';
|
||||
import { emitMapEvent, useMapEventListener } from '@/hooks/Mapper/events';
|
||||
@@ -48,7 +48,7 @@ export const MapWrapper = () => {
|
||||
linkSignatureToSystem,
|
||||
systemSignatures,
|
||||
},
|
||||
storedSettings: { interfaceSettings, settingsLocal },
|
||||
storedSettings: { interfaceSettings, settingsLocal, mapSettings, mapSettingsUpdate },
|
||||
} = useMapRootState();
|
||||
|
||||
const {
|
||||
@@ -83,8 +83,17 @@ export const MapWrapper = () => {
|
||||
systems,
|
||||
systemSignatures,
|
||||
deleteSystems,
|
||||
mapSettingsUpdate,
|
||||
});
|
||||
ref.current = { selectedConnections, selectedSystems, systemContextProps, systems, systemSignatures, deleteSystems };
|
||||
ref.current = {
|
||||
selectedConnections,
|
||||
selectedSystems,
|
||||
systemContextProps,
|
||||
systems,
|
||||
systemSignatures,
|
||||
deleteSystems,
|
||||
mapSettingsUpdate,
|
||||
};
|
||||
|
||||
useMapEventListener(event => {
|
||||
runCommand(event);
|
||||
@@ -121,6 +130,10 @@ export const MapWrapper = () => {
|
||||
[update],
|
||||
);
|
||||
|
||||
const handleChangeViewport = useCallback((viewport: Viewport) => {
|
||||
ref.current.mapSettingsUpdate({ viewport });
|
||||
}, []);
|
||||
|
||||
const handleCommand: OutCommandHandler = useCallback(
|
||||
event => {
|
||||
switch (event.type) {
|
||||
@@ -259,6 +272,7 @@ export const MapWrapper = () => {
|
||||
onConnectionInfoClick={handleConnectionDbClick}
|
||||
onSystemContextMenu={handleSystemContextMenu}
|
||||
onSelectionContextMenu={handleSystemMultipleContext}
|
||||
onChangeViewport={handleChangeViewport}
|
||||
minimapClasses={minimapClasses}
|
||||
isShowMinimap={showMinimap}
|
||||
showKSpaceBG={isShowKSpace}
|
||||
@@ -270,6 +284,7 @@ export const MapWrapper = () => {
|
||||
onAddSystem={onAddSystem}
|
||||
minimapPlacement={minimapPosition}
|
||||
localShowShipName={settingsLocal.showShipName}
|
||||
defaultViewport={mapSettings.viewport}
|
||||
/>
|
||||
|
||||
{openSettings != null && (
|
||||
|
||||
@@ -14,6 +14,7 @@ export type SystemViewStandaloneStatic = Pick<
|
||||
export type SystemViewStandaloneProps = {
|
||||
hideRegion?: boolean;
|
||||
customName?: string;
|
||||
nameClassName?: string;
|
||||
compact?: boolean;
|
||||
onContextMenu?(e: MouseEvent, systemId: string): void;
|
||||
} & WithClassName &
|
||||
@@ -23,6 +24,7 @@ export type SystemViewStandaloneProps = {
|
||||
|
||||
export const SystemViewStandalone = ({
|
||||
className,
|
||||
nameClassName,
|
||||
hideRegion,
|
||||
customName,
|
||||
class_title,
|
||||
@@ -57,10 +59,14 @@ export const SystemViewStandalone = ({
|
||||
>
|
||||
<span className={clsx(classTitleColor)}>{class_title}</span>
|
||||
<span
|
||||
className={clsx('text-gray-200 whitespace-nowrap', {
|
||||
['overflow-hidden text-ellipsis']: compact,
|
||||
[classes.CompactName]: compact,
|
||||
})}
|
||||
className={clsx(
|
||||
'text-gray-200 whitespace-nowrap',
|
||||
{
|
||||
['overflow-hidden text-ellipsis']: compact,
|
||||
[classes.CompactName]: compact,
|
||||
},
|
||||
nameClassName,
|
||||
)}
|
||||
>
|
||||
{customName ?? solar_system_name}
|
||||
</span>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import classes from './WHClassView.module.scss';
|
||||
import { Tooltip } from 'primereact/tooltip';
|
||||
import clsx from 'clsx';
|
||||
import { InfoDrawer } from '@/hooks/Mapper/components/ui-kit/InfoDrawer';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { WORMHOLE_CLASS_STYLES, WORMHOLES_ADDITIONAL_INFO } from '@/hooks/Mapper/components/map/constants.ts';
|
||||
import { useMemo } from 'react';
|
||||
import { TooltipPosition, WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
const prepareMass = (mass: number) => {
|
||||
if (mass === 0) {
|
||||
@@ -45,19 +45,28 @@ export const WHClassView = ({
|
||||
const whClass = useMemo(() => WORMHOLES_ADDITIONAL_INFO[whData.dest], [whData.dest]);
|
||||
const whClassStyle = WORMHOLE_CLASS_STYLES[whClass?.wormholeClassID] ?? '';
|
||||
|
||||
const uid = useMemo(() => new Date().getTime().toString(), []);
|
||||
const content = (
|
||||
<div
|
||||
className={clsx(classes.WHClassViewContent, { [classes.NoOffset]: noOffset }, 'wh-name select-none cursor-help')}
|
||||
>
|
||||
{!hideWhClassName && <span className={clsx({ [whClassStyle]: highlightName })}>{whClassName}</span>}
|
||||
{!hideWhClass && whClass && (
|
||||
<span className={clsx(classes.WHClassName, whClassStyle, classNameWh)}>
|
||||
{useShortTitle ? whClass.shortTitle : whClass.shortName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
if (hideTooltip) {
|
||||
return <div className={clsx(classes.WHClassViewRoot, className)}>{content}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={clsx(classes.WHClassViewRoot, className)}>
|
||||
{!hideTooltip && (
|
||||
<Tooltip
|
||||
target={`.wh-name${whClassName}${uid}`}
|
||||
position="right"
|
||||
mouseTrack
|
||||
mouseTrackLeft={20}
|
||||
mouseTrackTop={30}
|
||||
className="border border-green-300 rounded border-opacity-10 bg-stone-900 bg-opacity-90 "
|
||||
>
|
||||
<WdTooltipWrapper
|
||||
position={TooltipPosition.bottom}
|
||||
content={
|
||||
<div className="flex gap-3">
|
||||
<div className="flex flex-col gap-1">
|
||||
<InfoDrawer title="Total mass">{prepareMass(whData.total_mass)}</InfoDrawer>
|
||||
@@ -68,24 +77,10 @@ export const WHClassView = ({
|
||||
<InfoDrawer title="Mass regen">{prepareMass(whData.mass_regen)}</InfoDrawer>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={clsx(
|
||||
classes.WHClassViewContent,
|
||||
{ [classes.NoOffset]: noOffset },
|
||||
'wh-name select-none cursor-help',
|
||||
`wh-name${whClassName}${uid}`,
|
||||
)}
|
||||
}
|
||||
>
|
||||
{!hideWhClassName && <span className={clsx({ [whClassStyle]: highlightName })}>{whClassName}</span>}
|
||||
{!hideWhClass && whClass && (
|
||||
<span className={clsx(classes.WHClassName, whClassStyle, classNameWh)}>
|
||||
{useShortTitle ? whClass.shortTitle : whClass.shortName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{content}
|
||||
</WdTooltipWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
7
assets/js/hooks/Mapper/components/ui-kit/WdButton.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { Button, ButtonProps } from 'primereact/button';
|
||||
|
||||
export const WdButton = ({ type = 'button', ...props }: ButtonProps) => {
|
||||
// eslint-disable-next-line react/forbid-elements
|
||||
return <Button {...props} type={type} />;
|
||||
};
|
||||
@@ -0,0 +1,86 @@
|
||||
import { WdButton } from '@/hooks/Mapper/components/ui-kit/WdButton.tsx';
|
||||
import { TimeStatus } from '@/hooks/Mapper/types';
|
||||
import clsx from 'clsx';
|
||||
import { BUILT_IN_TOOLTIP_OPTIONS } from './constants.ts';
|
||||
|
||||
const LIFE_TIME = [
|
||||
{
|
||||
id: TimeStatus._1h,
|
||||
label: '1H',
|
||||
className: 'bg-purple-400 hover:!bg-purple-400',
|
||||
inactiveClassName: 'bg-purple-400/30',
|
||||
description: 'Less than one 1 hours remaining',
|
||||
},
|
||||
{
|
||||
id: TimeStatus._4h,
|
||||
label: '4H',
|
||||
className: 'bg-purple-300 hover:!bg-purple-300',
|
||||
inactiveClassName: 'bg-purple-300/30',
|
||||
description: 'Less than one 4 hours remaining',
|
||||
},
|
||||
{
|
||||
id: TimeStatus._4h30m,
|
||||
label: '4.5H',
|
||||
className: 'bg-indigo-300 hover:!bg-indigo-300',
|
||||
inactiveClassName: 'bg-indigo-300/30',
|
||||
description: 'Less than one 4.5 hours remaining. All small holes have such lifetime.',
|
||||
},
|
||||
{
|
||||
id: TimeStatus._16h,
|
||||
label: '16H',
|
||||
className: 'bg-orange-300 hover:!bg-orange-300',
|
||||
inactiveClassName: 'bg-orange-400/30',
|
||||
description: 'Less than one 16 hours remaining',
|
||||
},
|
||||
{
|
||||
id: TimeStatus._24h,
|
||||
label: '24H',
|
||||
className: 'bg-orange-300 hover:!bg-orange-300',
|
||||
inactiveClassName: 'bg-orange-400/30',
|
||||
description: 'Less than one 24 hours remaining',
|
||||
},
|
||||
{
|
||||
id: TimeStatus._48h,
|
||||
label: '48H',
|
||||
className: 'bg-orange-300 hover:!bg-orange-300',
|
||||
inactiveClassName: 'bg-orange-400/30',
|
||||
description: 'Less than one 24 hours remaining. Related only with C6. B041, B520, U319, C391.',
|
||||
},
|
||||
];
|
||||
|
||||
export interface WdLifetimeSelectorProps {
|
||||
lifetime?: TimeStatus;
|
||||
onChangeLifetime(lifetime: TimeStatus): void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const WdLifetimeSelector = ({
|
||||
lifetime = TimeStatus._24h,
|
||||
onChangeLifetime,
|
||||
className,
|
||||
}: WdLifetimeSelectorProps) => {
|
||||
return (
|
||||
<form>
|
||||
<div className={clsx('grid grid-cols-[1fr_1fr_1fr_1fr_1fr_1fr] gap-1', className)}>
|
||||
{LIFE_TIME.map(x => (
|
||||
<WdButton
|
||||
key={x.id}
|
||||
outlined={false}
|
||||
value={x.label}
|
||||
tooltip={x.description}
|
||||
tooltipOptions={BUILT_IN_TOOLTIP_OPTIONS}
|
||||
size="small"
|
||||
className={clsx(
|
||||
`py-[1px] justify-center min-w-auto w-auto border-0 text-[12px] font-bold leading-[20px]`,
|
||||
{ [x.inactiveClassName]: lifetime !== x.id },
|
||||
x.className,
|
||||
)}
|
||||
onClick={() => onChangeLifetime(x.id)}
|
||||
>
|
||||
{x.label}
|
||||
</WdButton>
|
||||
))}
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
6
assets/js/hooks/Mapper/components/ui-kit/constants.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const BUILT_IN_TOOLTIP_OPTIONS = {
|
||||
mouseTrack: true,
|
||||
mouseTrackLeft: 10,
|
||||
className:
|
||||
'rounded-[3px] bg-stone-900/90 px-1 py-1 [&_.p-tooltip-text]:!text-stone-300 text-[13px] [&_.p-tooltip-text]:!p-1',
|
||||
};
|
||||
@@ -21,3 +21,5 @@ export * from './LoadingWrapper';
|
||||
export * from './WdMenuItem';
|
||||
export * from './MenuItemWithInfo';
|
||||
export * from './MarkdownTextViewer.tsx';
|
||||
export * from './WdButton.tsx';
|
||||
export * from './constants.ts';
|
||||
|
||||
@@ -7,6 +7,8 @@ export enum SESSION_KEY {
|
||||
routes = 'routes',
|
||||
}
|
||||
|
||||
export const SYSTEM_FOCUSED_LIFETIME = 10000;
|
||||
|
||||
export const GRADIENT_MENU_ACTIVE_CLASSES = 'bg-gradient-to-br from-transparent/10 to-fuchsia-300/10';
|
||||
|
||||
export enum Regions {
|
||||
@@ -151,3 +153,11 @@ export const MINIMAP_PLACEMENT_MAP = {
|
||||
[PingsPlacement.rightBottom]: 'bottom-right',
|
||||
[PingsPlacement.leftBottom]: 'bottom-left',
|
||||
};
|
||||
|
||||
export const SPACE_TO_CLASS: Record<string, string> = {
|
||||
[Spaces.Caldari]: 'Caldaria',
|
||||
[Spaces.Matar]: 'Mataria',
|
||||
[Spaces.Amarr]: 'Amarria',
|
||||
[Spaces.Gallente]: 'Gallente',
|
||||
[Spaces.Pochven]: 'Pochven',
|
||||
};
|
||||
|
||||
@@ -5,3 +5,4 @@ export * from './useHotkey';
|
||||
export * from './usePageVisibility';
|
||||
export * from './useSkipContextMenu';
|
||||
export * from './useThrottle';
|
||||
export * from './useStableValue';
|
||||
|
||||
8
assets/js/hooks/Mapper/hooks/useStableValue.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { useRef } from 'react';
|
||||
import fastDeepEuqal from 'fast-deep-equal';
|
||||
|
||||
export const useStableValue = <T>(value: T): T => {
|
||||
const ref = useRef(value);
|
||||
if (!fastDeepEuqal(ref.current, value)) ref.current = value;
|
||||
return ref.current;
|
||||
};
|
||||
@@ -23,12 +23,14 @@ import {
|
||||
InterfaceStoredSettings,
|
||||
KillsWidgetSettings,
|
||||
LocalWidgetSettings,
|
||||
MapSettings,
|
||||
MapUserSettings,
|
||||
OnTheMapSettingsType,
|
||||
RoutesType,
|
||||
} from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import {
|
||||
DEFAULT_KILLS_WIDGET_SETTINGS,
|
||||
DEFAULT_MAP_SETTINGS,
|
||||
DEFAULT_ON_THE_MAP_SETTINGS,
|
||||
DEFAULT_ROUTES_SETTINGS,
|
||||
DEFAULT_WIDGET_LOCAL_SETTINGS,
|
||||
@@ -127,6 +129,8 @@ export interface MapRootContextProps {
|
||||
settingsOnTheMapUpdate: Dispatch<SetStateAction<OnTheMapSettingsType>>;
|
||||
settingsKills: KillsWidgetSettings;
|
||||
settingsKillsUpdate: Dispatch<SetStateAction<KillsWidgetSettings>>;
|
||||
mapSettings: MapSettings;
|
||||
mapSettingsUpdate: Dispatch<SetStateAction<MapSettings>>;
|
||||
isReady: boolean;
|
||||
hasOldSettings: boolean;
|
||||
getSettingsForExport(): string | undefined;
|
||||
@@ -172,6 +176,8 @@ const MapRootContext = createContext<MapRootContextProps>({
|
||||
settingsOnTheMapUpdate: () => null,
|
||||
settingsKills: DEFAULT_KILLS_WIDGET_SETTINGS,
|
||||
settingsKillsUpdate: () => null,
|
||||
mapSettings: DEFAULT_MAP_SETTINGS,
|
||||
mapSettingsUpdate: () => null,
|
||||
isReady: false,
|
||||
hasOldSettings: false,
|
||||
getSettingsForExport: () => '',
|
||||
|
||||
@@ -3,16 +3,13 @@ import {
|
||||
InterfaceStoredSettings,
|
||||
KillsWidgetSettings,
|
||||
LocalWidgetSettings,
|
||||
MapSettings,
|
||||
MiniMapPlacement,
|
||||
OnTheMapSettingsType,
|
||||
PingsPlacement,
|
||||
RoutesType,
|
||||
} from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import {
|
||||
CURRENT_WINDOWS_VERSION,
|
||||
DEFAULT_WIDGETS,
|
||||
STORED_VISIBLE_WIDGETS_DEFAULT,
|
||||
} from '@/hooks/Mapper/components/mapInterface/constants.tsx';
|
||||
import { DEFAULT_WIDGETS, STORED_VISIBLE_WIDGETS_DEFAULT } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
|
||||
|
||||
export const STORED_INTERFACE_DEFAULT_VALUES: InterfaceStoredSettings = {
|
||||
isShowMenu: false,
|
||||
@@ -43,25 +40,25 @@ export const DEFAULT_ROUTES_SETTINGS: RoutesType = {
|
||||
export const DEFAULT_WIDGET_LOCAL_SETTINGS: LocalWidgetSettings = {
|
||||
compact: true,
|
||||
showOffline: false,
|
||||
version: 0,
|
||||
showShipName: false,
|
||||
};
|
||||
|
||||
export const DEFAULT_ON_THE_MAP_SETTINGS: OnTheMapSettingsType = {
|
||||
hideOffline: false,
|
||||
version: 0,
|
||||
};
|
||||
|
||||
export const DEFAULT_KILLS_WIDGET_SETTINGS: KillsWidgetSettings = {
|
||||
showAll: false,
|
||||
whOnly: true,
|
||||
excludedSystems: [],
|
||||
version: 2,
|
||||
timeRange: 4,
|
||||
};
|
||||
|
||||
export const DEFAULT_MAP_SETTINGS: MapSettings = {
|
||||
viewport: { zoom: 1, x: 0, y: 0 },
|
||||
};
|
||||
|
||||
export const getDefaultWidgetProps = () => ({
|
||||
version: CURRENT_WINDOWS_VERSION,
|
||||
visible: STORED_VISIBLE_WIDGETS_DEFAULT,
|
||||
windows: DEFAULT_WIDGETS,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { MapUserSettings, SettingsTypes, SettingsWrapper } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import {
|
||||
DEFAULT_KILLS_WIDGET_SETTINGS,
|
||||
DEFAULT_MAP_SETTINGS,
|
||||
DEFAULT_ON_THE_MAP_SETTINGS,
|
||||
DEFAULT_ROUTES_SETTINGS,
|
||||
DEFAULT_WIDGET_LOCAL_SETTINGS,
|
||||
getDefaultWidgetProps,
|
||||
STORED_INTERFACE_DEFAULT_VALUES,
|
||||
} from '@/hooks/Mapper/mapRootProvider/constants.ts';
|
||||
import { DEFAULT_SIGNATURE_SETTINGS } from '@/hooks/Mapper/constants/signatures.ts';
|
||||
import { STORED_SETTINGS_VERSION } from '@/hooks/Mapper/mapRootProvider/version.ts';
|
||||
|
||||
// TODO - we need provide and compare version
|
||||
export const createWidgetSettings = <T>(settings: T) => {
|
||||
return settings;
|
||||
};
|
||||
|
||||
export const createDefaultStoredSettings = (): MapUserSettings => {
|
||||
return {
|
||||
version: STORED_SETTINGS_VERSION,
|
||||
migratedFromOld: true,
|
||||
killsWidget: createWidgetSettings(DEFAULT_KILLS_WIDGET_SETTINGS),
|
||||
localWidget: createWidgetSettings(DEFAULT_WIDGET_LOCAL_SETTINGS),
|
||||
widgets: createWidgetSettings(getDefaultWidgetProps()),
|
||||
routes: createWidgetSettings(DEFAULT_ROUTES_SETTINGS),
|
||||
onTheMap: createWidgetSettings(DEFAULT_ON_THE_MAP_SETTINGS),
|
||||
signaturesWidget: createWidgetSettings(DEFAULT_SIGNATURE_SETTINGS),
|
||||
interface: createWidgetSettings(STORED_INTERFACE_DEFAULT_VALUES),
|
||||
map: createWidgetSettings(DEFAULT_MAP_SETTINGS),
|
||||
};
|
||||
};
|
||||
|
||||
// INFO - in another case need to generate complex type - but looks like it unnecessary
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const getDefaultSettingsByType = (type: SettingsTypes): SettingsWrapper<any> => {
|
||||
switch (type) {
|
||||
case SettingsTypes.killsWidget:
|
||||
return createWidgetSettings(DEFAULT_KILLS_WIDGET_SETTINGS);
|
||||
case SettingsTypes.localWidget:
|
||||
return createWidgetSettings(DEFAULT_WIDGET_LOCAL_SETTINGS);
|
||||
case SettingsTypes.widgets:
|
||||
return createWidgetSettings(getDefaultWidgetProps());
|
||||
case SettingsTypes.routes:
|
||||
return createWidgetSettings(DEFAULT_ROUTES_SETTINGS);
|
||||
case SettingsTypes.onTheMap:
|
||||
return createWidgetSettings(DEFAULT_ON_THE_MAP_SETTINGS);
|
||||
case SettingsTypes.signaturesWidget:
|
||||
return createWidgetSettings(DEFAULT_SIGNATURE_SETTINGS);
|
||||
case SettingsTypes.interface:
|
||||
return createWidgetSettings(STORED_INTERFACE_DEFAULT_VALUES);
|
||||
case SettingsTypes.map:
|
||||
return createWidgetSettings(DEFAULT_MAP_SETTINGS);
|
||||
}
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { MapUserSettings } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import {
|
||||
DEFAULT_KILLS_WIDGET_SETTINGS,
|
||||
DEFAULT_ON_THE_MAP_SETTINGS,
|
||||
DEFAULT_ROUTES_SETTINGS,
|
||||
DEFAULT_WIDGET_LOCAL_SETTINGS,
|
||||
getDefaultWidgetProps,
|
||||
STORED_INTERFACE_DEFAULT_VALUES,
|
||||
} from '@/hooks/Mapper/mapRootProvider/constants.ts';
|
||||
import { DEFAULT_SIGNATURE_SETTINGS } from '@/hooks/Mapper/constants/signatures.ts';
|
||||
|
||||
// TODO - we need provide and compare version
|
||||
const createWidgetSettingsWithVersion = <T>(settings: T) => {
|
||||
return {
|
||||
version: 0,
|
||||
settings,
|
||||
};
|
||||
};
|
||||
|
||||
export const createDefaultWidgetSettings = (): MapUserSettings => {
|
||||
return {
|
||||
killsWidget: createWidgetSettingsWithVersion(DEFAULT_KILLS_WIDGET_SETTINGS),
|
||||
localWidget: createWidgetSettingsWithVersion(DEFAULT_WIDGET_LOCAL_SETTINGS),
|
||||
widgets: createWidgetSettingsWithVersion(getDefaultWidgetProps()),
|
||||
routes: createWidgetSettingsWithVersion(DEFAULT_ROUTES_SETTINGS),
|
||||
onTheMap: createWidgetSettingsWithVersion(DEFAULT_ON_THE_MAP_SETTINGS),
|
||||
signaturesWidget: createWidgetSettingsWithVersion(DEFAULT_SIGNATURE_SETTINGS),
|
||||
interface: createWidgetSettingsWithVersion(STORED_INTERFACE_DEFAULT_VALUES),
|
||||
};
|
||||
};
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
MapUserSettingsStructure,
|
||||
RemoteAdminSettingsResponse,
|
||||
} from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { createDefaultWidgetSettings } from '@/hooks/Mapper/mapRootProvider/helpers/createDefaultWidgetSettings.ts';
|
||||
import { parseMapUserSettings } from '@/hooks/Mapper/components/helpers';
|
||||
import { createDefaultStoredSettings } from '@/hooks/Mapper/mapRootProvider/helpers/createDefaultStoredSettings.ts';
|
||||
import { applyMigrations } from '@/hooks/Mapper/mapRootProvider/migrations';
|
||||
|
||||
interface UseActualizeRemoteMapSettingsProps {
|
||||
outCommand: OutCommandHandler;
|
||||
@@ -37,14 +37,14 @@ export const useActualizeRemoteMapSettings = ({
|
||||
}
|
||||
|
||||
if (res?.default_settings == null) {
|
||||
applySettings(createDefaultWidgetSettings());
|
||||
applySettings(createDefaultStoredSettings());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
applySettings(parseMapUserSettings(res.default_settings));
|
||||
applySettings(applyMigrations(JSON.parse(res.default_settings) || createDefaultStoredSettings()));
|
||||
} catch (error) {
|
||||
applySettings(createDefaultWidgetSettings());
|
||||
applySettings(createDefaultStoredSettings());
|
||||
}
|
||||
}, [outCommand]);
|
||||
|
||||
|
||||
@@ -63,123 +63,127 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
|
||||
const { pingAdded, pingCancelled } = useCommandPings();
|
||||
const { characterActivityData, trackingCharactersData, userSettingsUpdated } = useCommandsActivity();
|
||||
|
||||
useImperativeHandle(ref, () => {
|
||||
return {
|
||||
command(type, data) {
|
||||
switch (type) {
|
||||
case Commands.init: // USED
|
||||
mapInit(data as CommandInit);
|
||||
break;
|
||||
case Commands.addSystems: // USED
|
||||
addSystems(data as CommandAddSystems);
|
||||
break;
|
||||
case Commands.updateSystems: // USED
|
||||
updateSystems(data as CommandUpdateSystems);
|
||||
break;
|
||||
case Commands.removeSystems: // USED
|
||||
removeSystems(data as CommandRemoveSystems);
|
||||
break;
|
||||
case Commands.addConnections: // USED
|
||||
addConnections(data as CommandAddConnections);
|
||||
break;
|
||||
case Commands.removeConnections: // USED
|
||||
removeConnections(data as CommandRemoveConnections);
|
||||
break;
|
||||
case Commands.updateConnection: // USED
|
||||
updateConnection(data as CommandUpdateConnection);
|
||||
break;
|
||||
case Commands.charactersUpdated: // USED
|
||||
charactersUpdated(data as CommandCharactersUpdated);
|
||||
break;
|
||||
case Commands.characterAdded: // USED
|
||||
characterAdded(data as CommandCharacterAdded);
|
||||
break;
|
||||
case Commands.characterRemoved: // USED
|
||||
characterRemoved(data as CommandCharacterRemoved);
|
||||
break;
|
||||
case Commands.characterUpdated: // USED
|
||||
characterUpdated(data as CommandCharacterUpdated);
|
||||
break;
|
||||
case Commands.presentCharacters: // USED
|
||||
presentCharacters(data as CommandPresentCharacters);
|
||||
break;
|
||||
case Commands.mapUpdated: // USED
|
||||
mapUpdated(data as CommandMapUpdated);
|
||||
break;
|
||||
case Commands.routes:
|
||||
mapRoutes(data as CommandRoutes);
|
||||
break;
|
||||
case Commands.userRoutes:
|
||||
mapUserRoutes(data as CommandRoutes);
|
||||
break;
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => {
|
||||
return {
|
||||
command(type, data) {
|
||||
switch (type) {
|
||||
case Commands.init: // USED
|
||||
mapInit(data as CommandInit);
|
||||
break;
|
||||
case Commands.addSystems: // USED
|
||||
addSystems(data as CommandAddSystems);
|
||||
break;
|
||||
case Commands.updateSystems: // USED
|
||||
updateSystems(data as CommandUpdateSystems);
|
||||
break;
|
||||
case Commands.removeSystems: // USED
|
||||
removeSystems(data as CommandRemoveSystems);
|
||||
break;
|
||||
case Commands.addConnections: // USED
|
||||
addConnections(data as CommandAddConnections);
|
||||
break;
|
||||
case Commands.removeConnections: // USED
|
||||
removeConnections(data as CommandRemoveConnections);
|
||||
break;
|
||||
case Commands.updateConnection: // USED
|
||||
updateConnection(data as CommandUpdateConnection);
|
||||
break;
|
||||
case Commands.charactersUpdated: // USED
|
||||
charactersUpdated(data as CommandCharactersUpdated);
|
||||
break;
|
||||
case Commands.characterAdded: // USED
|
||||
characterAdded(data as CommandCharacterAdded);
|
||||
break;
|
||||
case Commands.characterRemoved: // USED
|
||||
characterRemoved(data as CommandCharacterRemoved);
|
||||
break;
|
||||
case Commands.characterUpdated: // USED
|
||||
characterUpdated(data as CommandCharacterUpdated);
|
||||
break;
|
||||
case Commands.presentCharacters: // USED
|
||||
presentCharacters(data as CommandPresentCharacters);
|
||||
break;
|
||||
case Commands.mapUpdated: // USED
|
||||
mapUpdated(data as CommandMapUpdated);
|
||||
break;
|
||||
case Commands.routes:
|
||||
mapRoutes(data as CommandRoutes);
|
||||
break;
|
||||
case Commands.userRoutes:
|
||||
mapUserRoutes(data as CommandRoutes);
|
||||
break;
|
||||
|
||||
case Commands.signaturesUpdated: // USED
|
||||
updateSystemSignatures(data as CommandSignaturesUpdated);
|
||||
break;
|
||||
case Commands.signaturesUpdated: // USED
|
||||
updateSystemSignatures(data as CommandSignaturesUpdated);
|
||||
break;
|
||||
|
||||
case Commands.linkSignatureToSystem: // USED
|
||||
setTimeout(() => {
|
||||
updateLinkSignatureToSystem(data as CommandLinkSignatureToSystem);
|
||||
}, 200);
|
||||
break;
|
||||
case Commands.linkSignatureToSystem: // USED
|
||||
setTimeout(() => {
|
||||
updateLinkSignatureToSystem(data as CommandLinkSignatureToSystem);
|
||||
}, 200);
|
||||
break;
|
||||
|
||||
case Commands.centerSystem: // USED
|
||||
// do nothing here
|
||||
break;
|
||||
case Commands.centerSystem: // USED
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.selectSystem: // USED
|
||||
// do nothing here
|
||||
break;
|
||||
case Commands.selectSystem: // USED
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.killsUpdated:
|
||||
// do nothing here
|
||||
break;
|
||||
case Commands.killsUpdated:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.detailedKillsUpdated:
|
||||
updateDetailedKills(data as Record<string, DetailedKill[]>);
|
||||
break;
|
||||
case Commands.detailedKillsUpdated:
|
||||
updateDetailedKills(data as Record<string, DetailedKill[]>);
|
||||
break;
|
||||
|
||||
case Commands.characterActivityData:
|
||||
characterActivityData(data as CommandCharacterActivityData);
|
||||
break;
|
||||
case Commands.characterActivityData:
|
||||
characterActivityData(data as CommandCharacterActivityData);
|
||||
break;
|
||||
|
||||
case Commands.trackingCharactersData:
|
||||
trackingCharactersData(data as CommandTrackingCharactersData);
|
||||
break;
|
||||
case Commands.trackingCharactersData:
|
||||
trackingCharactersData(data as CommandTrackingCharactersData);
|
||||
break;
|
||||
|
||||
case Commands.updateActivity:
|
||||
break;
|
||||
case Commands.updateActivity:
|
||||
break;
|
||||
|
||||
case Commands.updateTracking:
|
||||
break;
|
||||
case Commands.updateTracking:
|
||||
break;
|
||||
|
||||
case Commands.userSettingsUpdated:
|
||||
userSettingsUpdated(data as CommandUserSettingsUpdated);
|
||||
break;
|
||||
case Commands.userSettingsUpdated:
|
||||
userSettingsUpdated(data as CommandUserSettingsUpdated);
|
||||
break;
|
||||
|
||||
case Commands.systemCommentAdded:
|
||||
addComment(data as CommandCommentAdd);
|
||||
break;
|
||||
case Commands.systemCommentAdded:
|
||||
addComment(data as CommandCommentAdd);
|
||||
break;
|
||||
|
||||
case Commands.systemCommentRemoved:
|
||||
removeComment(data as CommandCommentRemoved);
|
||||
break;
|
||||
case Commands.systemCommentRemoved:
|
||||
removeComment(data as CommandCommentRemoved);
|
||||
break;
|
||||
|
||||
case Commands.pingAdded:
|
||||
pingAdded(data as CommandPingAdded);
|
||||
break;
|
||||
case Commands.pingAdded:
|
||||
pingAdded(data as CommandPingAdded);
|
||||
break;
|
||||
|
||||
case Commands.pingCancelled:
|
||||
pingCancelled(data as CommandPingCancelled);
|
||||
break;
|
||||
case Commands.pingCancelled:
|
||||
pingCancelled(data as CommandPingCancelled);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn(`JOipP Interface handlers: Unknown command: ${type}`, data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.warn(`JOipP Interface handlers: Unknown command: ${type}`, data);
|
||||
break;
|
||||
}
|
||||
|
||||
emitMapEvent({ name: type, data });
|
||||
},
|
||||
};
|
||||
}, []);
|
||||
emitMapEvent({ name: type, data });
|
||||
},
|
||||
};
|
||||
},
|
||||
[],
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,9 @@ import { useSettingsValueAndSetter } from '@/hooks/Mapper/mapRootProvider/hooks/
|
||||
import fastDeepEqual from 'fast-deep-equal';
|
||||
import { OutCommandHandler } from '@/hooks/Mapper/types';
|
||||
import { useActualizeRemoteMapSettings } from '@/hooks/Mapper/mapRootProvider/hooks/useActualizeRemoteMapSettings.ts';
|
||||
import { createDefaultWidgetSettings } from '@/hooks/Mapper/mapRootProvider/helpers/createDefaultWidgetSettings.ts';
|
||||
import { createDefaultStoredSettings } from '@/hooks/Mapper/mapRootProvider/helpers/createDefaultStoredSettings.ts';
|
||||
import { applyMigrations, extractData } from '@/hooks/Mapper/mapRootProvider/migrations';
|
||||
import { LS_KEY, LS_KEY_LEGASY } from '@/hooks/Mapper/mapRootProvider/version.ts';
|
||||
|
||||
const EMPTY_OBJ = {};
|
||||
|
||||
@@ -14,7 +16,7 @@ export const useMapUserSettings = ({ map_slug }: MapRootData, outCommand: OutCom
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
const [hasOldSettings, setHasOldSettings] = useState(false);
|
||||
|
||||
const [mapUserSettings, setMapUserSettings] = useLocalStorageState<MapUserSettingsStructure>('map-user-settings', {
|
||||
const [mapUserSettings, setMapUserSettings] = useLocalStorageState<MapUserSettingsStructure>(LS_KEY, {
|
||||
defaultValue: EMPTY_OBJ,
|
||||
});
|
||||
|
||||
@@ -83,13 +85,20 @@ export const useMapUserSettings = ({ map_slug }: MapRootData, outCommand: OutCom
|
||||
'killsWidget',
|
||||
);
|
||||
|
||||
const [windowsSettings, setWindowsSettings] = useSettingsValueAndSetter(
|
||||
const [windowsSettings, windowsSettingsUpdate] = useSettingsValueAndSetter(
|
||||
mapUserSettings,
|
||||
setMapUserSettings,
|
||||
map_slug,
|
||||
'widgets',
|
||||
);
|
||||
|
||||
const [mapSettings, mapSettingsUpdate] = useSettingsValueAndSetter(
|
||||
mapUserSettings,
|
||||
setMapUserSettings,
|
||||
map_slug,
|
||||
'map',
|
||||
);
|
||||
|
||||
// HERE we MUST work with migrations
|
||||
useEffect(() => {
|
||||
if (isReady) {
|
||||
@@ -100,36 +109,28 @@ export const useMapUserSettings = ({ map_slug }: MapRootData, outCommand: OutCom
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapUserSettings[map_slug] == null) {
|
||||
const currentMapUserSettings = mapUserSettings[map_slug];
|
||||
if (currentMapUserSettings == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO !!!! FROM this date 06.07.2025 - we must work only with migrations
|
||||
// actualizeSettings(STORED_INTERFACE_DEFAULT_VALUES, interfaceSettings, setInterfaceSettings);
|
||||
// actualizeSettings(DEFAULT_ROUTES_SETTINGS, settingsRoutes, settingsRoutesUpdate);
|
||||
// actualizeSettings(DEFAULT_WIDGET_LOCAL_SETTINGS, settingsLocal, settingsLocalUpdate);
|
||||
// actualizeSettings(DEFAULT_SIGNATURE_SETTINGS, settingsSignatures, settingsSignaturesUpdate);
|
||||
// actualizeSettings(DEFAULT_ON_THE_MAP_SETTINGS, settingsOnTheMap, settingsOnTheMapUpdate);
|
||||
// actualizeSettings(DEFAULT_KILLS_WIDGET_SETTINGS, settingsKills, settingsKillsUpdate);
|
||||
try {
|
||||
// INFO: after migrations migratedFromOld always will be true
|
||||
const migratedResult = applyMigrations(
|
||||
!currentMapUserSettings.migratedFromOld ? extractData(LS_KEY_LEGASY) : currentMapUserSettings,
|
||||
);
|
||||
|
||||
setIsReady(true);
|
||||
}, [
|
||||
map_slug,
|
||||
mapUserSettings,
|
||||
interfaceSettings,
|
||||
setInterfaceSettings,
|
||||
settingsRoutes,
|
||||
settingsRoutesUpdate,
|
||||
settingsLocal,
|
||||
settingsLocalUpdate,
|
||||
settingsSignatures,
|
||||
settingsSignaturesUpdate,
|
||||
settingsOnTheMap,
|
||||
settingsOnTheMapUpdate,
|
||||
settingsKills,
|
||||
settingsKillsUpdate,
|
||||
isReady,
|
||||
]);
|
||||
if (!migratedResult) {
|
||||
setIsReady(true);
|
||||
return;
|
||||
}
|
||||
|
||||
setMapUserSettings({ ...mapUserSettings, [map_slug]: migratedResult });
|
||||
setIsReady(true);
|
||||
} catch (error) {
|
||||
setIsReady(true);
|
||||
}
|
||||
}, [isReady, mapUserSettings, map_slug, setMapUserSettings]);
|
||||
|
||||
const checkOldSettings = useCallback(() => {
|
||||
const interfaceSettings = localStorage.getItem('window:interface:settings');
|
||||
@@ -157,7 +158,7 @@ export const useMapUserSettings = ({ map_slug }: MapRootData, outCommand: OutCom
|
||||
}, []);
|
||||
|
||||
const resetSettings = useCallback(() => {
|
||||
applySettings(createDefaultWidgetSettings());
|
||||
applySettings(createDefaultStoredSettings());
|
||||
}, [applySettings]);
|
||||
|
||||
return {
|
||||
@@ -177,7 +178,9 @@ export const useMapUserSettings = ({ map_slug }: MapRootData, outCommand: OutCom
|
||||
settingsKills,
|
||||
settingsKillsUpdate,
|
||||
windowsSettings,
|
||||
setWindowsSettings,
|
||||
windowsSettingsUpdate,
|
||||
mapSettings,
|
||||
mapSettingsUpdate,
|
||||
|
||||
getSettingsForExport,
|
||||
applySettings,
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import { Dispatch, SetStateAction, useCallback, useMemo, useRef } from 'react';
|
||||
import {
|
||||
MapUserSettings,
|
||||
MapUserSettingsStructure,
|
||||
SettingsWithVersion,
|
||||
} from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { MapUserSettings, MapUserSettingsStructure, SettingsWrapper } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
|
||||
type ExtractSettings<S extends keyof MapUserSettings> =
|
||||
MapUserSettings[S] extends SettingsWithVersion<infer U> ? U : never;
|
||||
type ExtractSettings<S extends keyof MapUserSettings> = MapUserSettings[S] extends SettingsWrapper<infer U> ? U : never;
|
||||
|
||||
type Setter<S extends keyof MapUserSettings> = (
|
||||
value: Partial<ExtractSettings<S>> | ((prev: ExtractSettings<S>) => Partial<ExtractSettings<S>>),
|
||||
version?: number,
|
||||
) => void;
|
||||
|
||||
type GenerateSettingsReturn<S extends keyof MapUserSettings> = [ExtractSettings<S>, Setter<S>];
|
||||
@@ -24,7 +20,7 @@ export const useSettingsValueAndSetter = <S extends keyof MapUserSettings>(
|
||||
if (!mapId) return {} as ExtractSettings<S>;
|
||||
|
||||
const mapSettings = settings[mapId];
|
||||
return (mapSettings?.[setting]?.settings ?? ({} as ExtractSettings<S>)) as ExtractSettings<S>;
|
||||
return (mapSettings?.[setting] ?? ({} as ExtractSettings<S>)) as ExtractSettings<S>;
|
||||
}, [mapId, setting, settings]);
|
||||
|
||||
const refData = useRef({ mapId, setting, setSettings });
|
||||
@@ -37,8 +33,7 @@ export const useSettingsValueAndSetter = <S extends keyof MapUserSettings>(
|
||||
|
||||
setSettings(all => {
|
||||
const currentMap = all[mapId];
|
||||
const prev = currentMap[setting].settings as ExtractSettings<S>;
|
||||
const version = currentMap[setting].version;
|
||||
const prev = currentMap[setting] as ExtractSettings<S>;
|
||||
|
||||
const patch =
|
||||
typeof value === 'function' ? (value as (p: ExtractSettings<S>) => Partial<ExtractSettings<S>>)(prev) : value;
|
||||
@@ -47,10 +42,7 @@ export const useSettingsValueAndSetter = <S extends keyof MapUserSettings>(
|
||||
...all,
|
||||
[mapId]: {
|
||||
...currentMap,
|
||||
[setting]: {
|
||||
version,
|
||||
settings: { ...(prev as any), ...patch } as ExtractSettings<S>,
|
||||
},
|
||||
[setting]: { ...(prev as any), ...patch } as ExtractSettings<S>,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@ import { getDefaultWidgetProps } from '@/hooks/Mapper/mapRootProvider/constants.
|
||||
|
||||
export type StoredWindowProps = Omit<WindowProps, 'content'>;
|
||||
export type WindowStoreInfo = {
|
||||
version: number;
|
||||
windows: StoredWindowProps[];
|
||||
visible: WidgetsIds[];
|
||||
viewPort?: { w: number; h: number } | undefined;
|
||||
@@ -16,19 +15,18 @@ export type ToggleWidgetVisibility = (widgetId: WidgetsIds) => void;
|
||||
|
||||
interface UseStoreWidgetsProps {
|
||||
windowsSettings: WindowStoreInfo;
|
||||
setWindowsSettings: Dispatch<SetStateAction<WindowStoreInfo>>;
|
||||
windowsSettingsUpdate: Dispatch<SetStateAction<WindowStoreInfo>>;
|
||||
}
|
||||
|
||||
export const useStoreWidgets = ({ windowsSettings, setWindowsSettings }: UseStoreWidgetsProps) => {
|
||||
const ref = useRef({ windowsSettings, setWindowsSettings });
|
||||
ref.current = { windowsSettings, setWindowsSettings };
|
||||
export const useStoreWidgets = ({ windowsSettings, windowsSettingsUpdate }: UseStoreWidgetsProps) => {
|
||||
const ref = useRef({ windowsSettings, windowsSettingsUpdate });
|
||||
ref.current = { windowsSettings, windowsSettingsUpdate };
|
||||
|
||||
const updateWidgetSettings: WindowsManagerOnChange = useCallback(({ windows, viewPort }) => {
|
||||
const { setWindowsSettings } = ref.current;
|
||||
const { windowsSettingsUpdate } = ref.current;
|
||||
|
||||
setWindowsSettings(({ version, visible /*, windows*/ }: WindowStoreInfo) => {
|
||||
windowsSettingsUpdate(({ visible /*, windows*/ }: WindowStoreInfo) => {
|
||||
return {
|
||||
version,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
windows: DEFAULT_WIDGETS.map(({ content, ...x }) => {
|
||||
const windowProp = windows.find(j => j.id === x.id);
|
||||
@@ -45,9 +43,9 @@ export const useStoreWidgets = ({ windowsSettings, setWindowsSettings }: UseStor
|
||||
}, []);
|
||||
|
||||
const toggleWidgetVisibility: ToggleWidgetVisibility = useCallback(widgetId => {
|
||||
const { setWindowsSettings } = ref.current;
|
||||
const { windowsSettingsUpdate } = ref.current;
|
||||
|
||||
setWindowsSettings(({ visible, windows, ...x }) => {
|
||||
windowsSettingsUpdate(({ visible, windows, ...x }) => {
|
||||
const isCheckedPrev = visible.includes(widgetId);
|
||||
if (!isCheckedPrev) {
|
||||
const maxZIndex = Math.max(...windows.map(w => w.zIndex));
|
||||
@@ -72,7 +70,7 @@ export const useStoreWidgets = ({ windowsSettings, setWindowsSettings }: UseStor
|
||||
});
|
||||
}, []);
|
||||
|
||||
const resetWidgets = useCallback(() => ref.current.setWindowsSettings(getDefaultWidgetProps()), []);
|
||||
const resetWidgets = useCallback(() => ref.current.windowsSettingsUpdate(getDefaultWidgetProps()), []);
|
||||
|
||||
return {
|
||||
windowsSettings,
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { MapUserSettingsStructure } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
import { STORED_SETTINGS_VERSION } from '@/hooks/Mapper/mapRootProvider/version.ts';
|
||||
import { migrations } from '@/hooks/Mapper/mapRootProvider/migrations/index.ts';
|
||||
import { createDefaultStoredSettings } from '@/hooks/Mapper/mapRootProvider/helpers/createDefaultStoredSettings.ts';
|
||||
|
||||
export const extractData = (localStoreKey = 'map-user-settings'): MapUserSettingsStructure | null => {
|
||||
const val = localStorage.getItem(localStoreKey);
|
||||
if (!val) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSON.parse(val);
|
||||
};
|
||||
|
||||
export const applyMigrations = (mapSettings: any) => {
|
||||
let currentMapSettings = { ...mapSettings };
|
||||
|
||||
// INFO if we have NO any data in store expected that we will use default
|
||||
if (!currentMapSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
const direction = STORED_SETTINGS_VERSION - (currentMapSettings.version || 0);
|
||||
if (direction === 0) {
|
||||
if (currentMapSettings.version == null) {
|
||||
return { ...currentMapSettings, version: STORED_SETTINGS_VERSION, migratedFromOld: true };
|
||||
}
|
||||
|
||||
return currentMapSettings;
|
||||
}
|
||||
|
||||
const cmVersion = currentMapSettings.version || 0;
|
||||
|
||||
// downgrade
|
||||
// INFO: when we downgrading - if diff between >= 1 it means was major version
|
||||
if (direction < 0) {
|
||||
// If was minor version - we do nothing
|
||||
if (Math.abs(direction) < 1) {
|
||||
return currentMapSettings;
|
||||
}
|
||||
|
||||
// if was major version - we set default settings
|
||||
return createDefaultStoredSettings();
|
||||
}
|
||||
|
||||
const preparedMigrations = migrations
|
||||
.sort((a, b) => a.to - b.to)
|
||||
.filter(x => x.to > cmVersion && x.to <= STORED_SETTINGS_VERSION);
|
||||
|
||||
for (const migration of preparedMigrations) {
|
||||
const { to, up } = migration;
|
||||
|
||||
const next = up(currentMapSettings);
|
||||
currentMapSettings = { ...next, version: to, migratedFromOld: true };
|
||||
}
|
||||
|
||||
return currentMapSettings;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
import list from './list';
|
||||
export * from './applyMigrations.ts';
|
||||
|
||||
export const migrations = [...list];
|
||||
@@ -0,0 +1,5 @@
|
||||
import { to_1 } from './to_1.ts';
|
||||
import { to_2 } from './to_2.ts';
|
||||
import { MigrationStructure } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
|
||||
export default [to_1, to_2] as MigrationStructure[];
|
||||
@@ -0,0 +1,10 @@
|
||||
import { MigrationStructure } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
|
||||
export const to_1: MigrationStructure = {
|
||||
to: 1,
|
||||
up: (prev: any) => {
|
||||
return Object.keys(prev).reduce((acc, k) => {
|
||||
return { ...acc, [k]: prev[k].settings };
|
||||
}, Object.create(null));
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import { MigrationStructure } from '@/hooks/Mapper/mapRootProvider/types.ts';
|
||||
|
||||
const IN_V1_STORE_KEY = 'viewPort';
|
||||
const IN_V1_DEFAULT_VIEWPORT = { zoom: 1, x: 0, y: 0 };
|
||||
|
||||
export const to_2: MigrationStructure = {
|
||||
to: 2,
|
||||
up: (prev: any) => {
|
||||
const restored = localStorage.getItem(IN_V1_STORE_KEY);
|
||||
let current = IN_V1_DEFAULT_VIEWPORT;
|
||||
if (restored != null) {
|
||||
try {
|
||||
current = JSON.parse(restored);
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
localStorage.removeItem(IN_V1_STORE_KEY);
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
map: {
|
||||
viewport: current,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -50,36 +50,39 @@ export type RoutesType = {
|
||||
export type LocalWidgetSettings = {
|
||||
compact: boolean;
|
||||
showOffline: boolean;
|
||||
version: number;
|
||||
showShipName: boolean;
|
||||
};
|
||||
|
||||
export type OnTheMapSettingsType = {
|
||||
hideOffline: boolean;
|
||||
version: number;
|
||||
};
|
||||
|
||||
export type KillsWidgetSettings = {
|
||||
showAll: boolean;
|
||||
whOnly: boolean;
|
||||
excludedSystems: number[];
|
||||
version: number;
|
||||
timeRange: number;
|
||||
};
|
||||
|
||||
export type SettingsWithVersion<T> = {
|
||||
version: number;
|
||||
settings: T;
|
||||
export type MapViewPort = { zoom: number; x: number; y: number };
|
||||
|
||||
export type MapSettings = {
|
||||
viewport: MapViewPort;
|
||||
};
|
||||
|
||||
export type SettingsWrapper<T> = T;
|
||||
|
||||
export type MapUserSettings = {
|
||||
widgets: SettingsWithVersion<WindowStoreInfo>;
|
||||
interface: SettingsWithVersion<InterfaceStoredSettings>;
|
||||
onTheMap: SettingsWithVersion<OnTheMapSettingsType>;
|
||||
routes: SettingsWithVersion<RoutesType>;
|
||||
localWidget: SettingsWithVersion<LocalWidgetSettings>;
|
||||
signaturesWidget: SettingsWithVersion<SignatureSettingsType>;
|
||||
killsWidget: SettingsWithVersion<KillsWidgetSettings>;
|
||||
migratedFromOld: boolean;
|
||||
version: number;
|
||||
widgets: SettingsWrapper<WindowStoreInfo>;
|
||||
interface: SettingsWrapper<InterfaceStoredSettings>;
|
||||
onTheMap: SettingsWrapper<OnTheMapSettingsType>;
|
||||
routes: SettingsWrapper<RoutesType>;
|
||||
localWidget: SettingsWrapper<LocalWidgetSettings>;
|
||||
signaturesWidget: SettingsWrapper<SignatureSettingsType>;
|
||||
killsWidget: SettingsWrapper<KillsWidgetSettings>;
|
||||
map: SettingsWrapper<MapSettings>;
|
||||
};
|
||||
|
||||
export type MapUserSettingsStructure = {
|
||||
@@ -89,3 +92,20 @@ export type MapUserSettingsStructure = {
|
||||
export type WdResponse<T> = T;
|
||||
|
||||
export type RemoteAdminSettingsResponse = { default_settings?: string };
|
||||
|
||||
export enum SettingsTypes {
|
||||
killsWidget = 'killsWidget',
|
||||
localWidget = 'localWidget',
|
||||
widgets = 'widgets',
|
||||
routes = 'routes',
|
||||
onTheMap = 'onTheMap',
|
||||
signaturesWidget = 'signaturesWidget',
|
||||
interface = 'interface',
|
||||
map = 'map',
|
||||
}
|
||||
|
||||
export type MigrationFunc = (prev: any) => any;
|
||||
export type MigrationStructure = {
|
||||
to: number;
|
||||
up: MigrationFunc;
|
||||
};
|
||||
|
||||
4
assets/js/hooks/Mapper/mapRootProvider/version.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const STORED_SETTINGS_VERSION = 2;
|
||||
|
||||
export const LS_KEY_LEGASY = 'map-user-settings';
|
||||
export const LS_KEY = 'map-user-settings-v2';
|
||||
@@ -11,8 +11,13 @@ export enum MassState {
|
||||
}
|
||||
|
||||
export enum TimeStatus {
|
||||
default,
|
||||
eol,
|
||||
reserved, // TODO: this reserved for not broke prev solution
|
||||
_1h,
|
||||
_4h,
|
||||
_4h30m,
|
||||
_16h,
|
||||
_24h,
|
||||
_48h,
|
||||
}
|
||||
|
||||
export enum ShipSizeStatus {
|
||||
|
||||
@@ -122,7 +122,7 @@ export enum SignatureGroupRU {
|
||||
export enum SignatureGroupFR {
|
||||
CosmicSignature = 'Signature cosmique (groupe)',
|
||||
Wormhole = 'Trou de ver',
|
||||
GasSite = 'Site de gaz',
|
||||
GasSite = 'Site de collecte de gaz',
|
||||
RelicSite = 'Site de reliques',
|
||||
DataSite = 'Site de données',
|
||||
OreSite = 'Site de minerai',
|
||||
|
||||
@@ -118,6 +118,7 @@ export type SolarSystemRawType = {
|
||||
name: string | null;
|
||||
temporary_name: string | null;
|
||||
linked_sig_eve_id: string | null;
|
||||
comments_count: number | null;
|
||||
|
||||
system_static_info: SolarSystemStaticInfoRaw;
|
||||
system_signatures: SystemSignature[];
|
||||
|
||||
@@ -2,3 +2,4 @@ export * from './contextStore';
|
||||
export * from './getQueryVariable';
|
||||
export * from './loadTextFile';
|
||||
export * from './saveToFile';
|
||||
export * from './omit';
|
||||
|
||||
8
assets/js/hooks/Mapper/utils/omit.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const omit = <T extends Record<string, any>, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> => {
|
||||
const result = { ...obj };
|
||||
for (const key of keys) {
|
||||
delete result[key];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
@@ -4,7 +4,7 @@ import 'phoenix_html';
|
||||
import './live_reload.css';
|
||||
|
||||
const animateBg = function (bgCanvas) {
|
||||
const { TweenMax, _ } = window;
|
||||
const { TweenMax } = window;
|
||||
/**
|
||||
* Utility function for returning a random integer in a given range
|
||||
* @param {Int} max
|
||||
@@ -212,12 +212,6 @@ const animateBg = function (bgCanvas) {
|
||||
};
|
||||
}
|
||||
window.myJump = new JumpToHyperspace(bgCanvas);
|
||||
window.addEventListener(
|
||||
'resize',
|
||||
_.debounce(() => {
|
||||
window.myJump.reset();
|
||||
}, 250),
|
||||
);
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
BIN
assets/static/apple-touch-icon.png
Executable file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/static/favicon-96x96.png
Executable file
|
After Width: | Height: | Size: 977 B |
BIN
assets/static/images/amarr-small.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
33
assets/static/site.webmanifest
Executable file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "Wanderer",
|
||||
"short_name": "Wanderer",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/web-app-manifest-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/web-app-manifest-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#171717",
|
||||
"background_color": "#171717",
|
||||
"display": "standalone",
|
||||
"start_url": "/",
|
||||
"screenshots": [
|
||||
{
|
||||
"src": "web-app-manifest.webp",
|
||||
"sizes": "720x1280",
|
||||
"type": "image/webp"
|
||||
},
|
||||
{
|
||||
"src": "web-app-manifest-wide.webp",
|
||||
"sizes": "1280x720",
|
||||
"type": "image/webp",
|
||||
"form_factor": "wide"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
assets/static/web-app-manifest-192x192.png
Executable file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/static/web-app-manifest-512x512.png
Executable file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
assets/static/web-app-manifest-wide.webp
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
assets/static/web-app-manifest.webp
Normal file
|
After Width: | Height: | Size: 61 KiB |
@@ -147,8 +147,13 @@ defmodule WandererApp.Api.MapConnection do
|
||||
allow_nil?(true)
|
||||
end
|
||||
|
||||
# where 0 - normal
|
||||
# where 1 - end of life
|
||||
# 0 - normal (env settings)
|
||||
# 1 - EOL 1h
|
||||
# 2 - EOL 4h
|
||||
# 3 - EOL 4.5h
|
||||
# 4 - EOL 16h
|
||||
# 5 - EOL 24h
|
||||
# 6 - EOL 48h
|
||||
attribute :time_status, :integer do
|
||||
default(0)
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
end
|
||||
end
|
||||
end,
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task,
|
||||
timeout: :timer.seconds(60)
|
||||
)
|
||||
@@ -256,7 +256,7 @@ defmodule WandererApp.Character.TrackerManager.Impl do
|
||||
WandererApp.Character.update_character_state(character_id, character_state)
|
||||
WandererApp.Map.Server.Impl.broadcast!(map_id, :untrack_character, character_id)
|
||||
end,
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task,
|
||||
timeout: :timer.seconds(30)
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
@check_location_errors_interval :timer.minutes(1)
|
||||
@update_ship_interval :timer.seconds(2)
|
||||
@update_info_interval :timer.minutes(2)
|
||||
@update_wallet_interval :timer.minutes(1)
|
||||
@update_wallet_interval :timer.minutes(10)
|
||||
|
||||
@logger Application.compile_env(:wanderer_app, :logger)
|
||||
|
||||
@@ -180,7 +180,7 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
fn character_id ->
|
||||
WandererApp.Character.Tracker.update_online(character_id)
|
||||
end,
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task,
|
||||
timeout: :timer.seconds(5)
|
||||
)
|
||||
@@ -241,12 +241,12 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
WandererApp.Character.Tracker.check_offline(character_id)
|
||||
end,
|
||||
timeout: :timer.seconds(15),
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task
|
||||
)
|
||||
|> Enum.each(fn
|
||||
{:ok, _result} -> :ok
|
||||
{:error, reason} -> @logger.error("Error in check_offline: #{inspect(reason)}")
|
||||
error -> @logger.error("Error in check_offline: #{inspect(error)}")
|
||||
end)
|
||||
rescue
|
||||
e ->
|
||||
@@ -281,12 +281,12 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
)
|
||||
end,
|
||||
timeout: :timer.seconds(15),
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task
|
||||
)
|
||||
|> Enum.each(fn
|
||||
{:ok, _result} -> :ok
|
||||
{:error, reason} -> @logger.error("Error in check_online_errors: #{inspect(reason)}")
|
||||
error -> @logger.error("Error in check_online_errors: #{inspect(error)}")
|
||||
end)
|
||||
rescue
|
||||
e ->
|
||||
@@ -321,12 +321,12 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
)
|
||||
end,
|
||||
timeout: :timer.seconds(15),
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task
|
||||
)
|
||||
|> Enum.each(fn
|
||||
{:ok, _result} -> :ok
|
||||
{:error, reason} -> @logger.error("Error in check_ship_errors: #{inspect(reason)}")
|
||||
error -> @logger.error("Error in check_ship_errors: #{inspect(error)}")
|
||||
end)
|
||||
rescue
|
||||
e ->
|
||||
@@ -361,12 +361,12 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
)
|
||||
end,
|
||||
timeout: :timer.seconds(15),
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task
|
||||
)
|
||||
|> Enum.each(fn
|
||||
{:ok, _result} -> :ok
|
||||
{:error, reason} -> @logger.error("Error in check_location_errors: #{inspect(reason)}")
|
||||
error -> @logger.error("Error in check_location_errors: #{inspect(error)}")
|
||||
end)
|
||||
rescue
|
||||
e ->
|
||||
@@ -395,7 +395,7 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
fn character_id ->
|
||||
WandererApp.Character.Tracker.update_location(character_id)
|
||||
end,
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task,
|
||||
timeout: :timer.seconds(5)
|
||||
)
|
||||
@@ -436,7 +436,7 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
fn character_id ->
|
||||
WandererApp.Character.Tracker.update_ship(character_id)
|
||||
end,
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task,
|
||||
timeout: :timer.seconds(5)
|
||||
)
|
||||
@@ -478,12 +478,12 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
WandererApp.Character.Tracker.update_info(character_id)
|
||||
end,
|
||||
timeout: :timer.seconds(15),
|
||||
max_concurrency: System.schedulers_online(),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task
|
||||
)
|
||||
|> Enum.each(fn
|
||||
{:ok, _result} -> :ok
|
||||
{:error, reason} -> Logger.error("Error in update_info: #{inspect(reason)}")
|
||||
error -> Logger.error("Error in update_info: #{inspect(error)}")
|
||||
end)
|
||||
rescue
|
||||
e ->
|
||||
@@ -521,13 +521,13 @@ defmodule WandererApp.Character.TrackerPool do
|
||||
fn character_id ->
|
||||
WandererApp.Character.Tracker.update_wallet(character_id)
|
||||
end,
|
||||
timeout: :timer.seconds(15),
|
||||
max_concurrency: System.schedulers_online(),
|
||||
timeout: :timer.minutes(5),
|
||||
max_concurrency: System.schedulers_online() * 4,
|
||||
on_timeout: :kill_task
|
||||
)
|
||||
|> Enum.each(fn
|
||||
{:ok, _result} -> :ok
|
||||
{:error, reason} -> Logger.error("Error in update_wallet: #{inspect(reason)}")
|
||||
error -> Logger.error("Error in update_wallet: #{inspect(error)}")
|
||||
end)
|
||||
rescue
|
||||
e ->
|
||||
|
||||