mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-07 08:15:35 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc412e93c0 | ||
|
|
1d36fadbfa | ||
|
|
56182bd87d | ||
|
|
d290ff92b3 | ||
|
|
298c5fd3b8 | ||
|
|
e365c43781 | ||
|
|
23a9f22ef4 | ||
|
|
242f437237 | ||
|
|
2eae8cffdb | ||
|
|
68ab3d4f72 | ||
|
|
1ea805aff0 | ||
|
|
6ce45349dc | ||
|
|
8f20cd9863 | ||
|
|
4ed0e85680 | ||
|
|
8ce9eb9955 | ||
|
|
363330f3d1 | ||
|
|
fbf9c5ddd6 | ||
|
|
fbf2ee314c | ||
|
|
c9f83fb419 | ||
|
|
9737d91e16 | ||
|
|
2f672ae970 |
63
CHANGELOG.md
63
CHANGELOG.md
@@ -2,6 +2,69 @@
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.10.0](https://github.com/wanderer-industries/wanderer/compare/v1.9.0...v1.10.0) (2024-10-13)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Link signature on splash
|
||||
|
||||
## [v1.9.0](https://github.com/wanderer-industries/wanderer/compare/v1.8.0...v1.9.0) (2024-10-13)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Link signature on splash
|
||||
|
||||
## [v1.8.0](https://github.com/wanderer-industries/wanderer/compare/v1.7.0...v1.8.0) (2024-10-13)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Link signature on splash
|
||||
|
||||
## [v1.7.0](https://github.com/wanderer-industries/wanderer/compare/v1.6.0...v1.7.0) (2024-10-13)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Link signature on splash
|
||||
|
||||
## [v1.6.0](https://github.com/wanderer-industries/wanderer/compare/v1.5.0...v1.6.0) (2024-10-13)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Link signature on splash
|
||||
|
||||
## [v1.5.0](https://github.com/wanderer-industries/wanderer/compare/v1.4.0...v1.5.0) (2024-10-11)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Follow Character on Map and auto select their current system
|
||||
|
||||
## [v1.4.0](https://github.com/wanderer-industries/wanderer/compare/v1.3.6...v1.4.0) (2024-10-11)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* Map: Follow Character on Map and auto select their current system
|
||||
|
||||
## [v1.3.6](https://github.com/wanderer-industries/wanderer/compare/v1.3.5...v1.3.6) (2024-10-09)
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ const Characters = ({ data }: { data: CharacterTypeRaw[] }) => {
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(character: CharacterTypeRaw) => {
|
||||
mapRef.current?.command(Commands.selectSystem, character?.location?.solar_system_id?.toString());
|
||||
mapRef.current?.command(Commands.centerSystem, character?.location?.solar_system_id?.toString());
|
||||
},
|
||||
[mapRef],
|
||||
);
|
||||
|
||||
@@ -48,19 +48,19 @@ export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: U
|
||||
}, []);
|
||||
|
||||
const onAddSystem = useCallback(() => {
|
||||
const { system, outCommand, mapRef } = ref.current;
|
||||
if (!system) {
|
||||
const { system: solarSystemId, outCommand, mapRef } = ref.current;
|
||||
if (!solarSystemId) {
|
||||
return;
|
||||
}
|
||||
|
||||
outCommand({
|
||||
type: OutCommand.addSystem,
|
||||
data: {
|
||||
system_id: system,
|
||||
system_id: solarSystemId,
|
||||
},
|
||||
});
|
||||
setTimeout(() => {
|
||||
mapRef.current?.command(Commands.selectSystem, system);
|
||||
mapRef.current?.command(Commands.centerSystem, solarSystemId);
|
||||
setSystem(undefined);
|
||||
}, 200);
|
||||
}, []);
|
||||
|
||||
@@ -5,5 +5,6 @@ export * from './useMapRemoveSystems';
|
||||
export * from './useCommandsCharacters';
|
||||
export * from './useCommandsConnections';
|
||||
export * from './useCommandsConnections';
|
||||
export * from './useCenterSystem';
|
||||
export * from './useSelectSystem';
|
||||
export * from './useMapCommands';
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { useReactFlow } from 'reactflow';
|
||||
import { useCallback } from 'react';
|
||||
import { CommandCenterSystem } from '@/hooks/Mapper/types';
|
||||
|
||||
export const useCenterSystem = () => {
|
||||
const rf = useReactFlow();
|
||||
|
||||
return useCallback((systemId: CommandCenterSystem) => {
|
||||
if (!rf) {
|
||||
return;
|
||||
}
|
||||
const systemNode = rf.getNodes().find(x => x.data.id === systemId);
|
||||
if (!systemNode) {
|
||||
return;
|
||||
}
|
||||
rf.setCenter(systemNode.position.x, systemNode.position.y, { duration: 1000 });
|
||||
}, []);
|
||||
};
|
||||
@@ -1,21 +1,21 @@
|
||||
import { useReactFlow } from 'reactflow';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { CommandSelectSystem } from '@/hooks/Mapper/types';
|
||||
|
||||
export const useSelectSystem = () => {
|
||||
const rf = useReactFlow();
|
||||
const ref = useRef({ rf });
|
||||
ref.current = { rf };
|
||||
|
||||
return useCallback((systemId: CommandSelectSystem) => {
|
||||
if (!ref.current?.rf) {
|
||||
if (!rf) {
|
||||
return;
|
||||
}
|
||||
const systemNode = ref.current.rf.getNodes().find(x => x.data.id === systemId);
|
||||
if (!systemNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
ref.current.rf.setCenter(systemNode.position.x, systemNode.position.y, { duration: 1000 });
|
||||
rf.setNodes(nds =>
|
||||
nds.map(node => {
|
||||
return {
|
||||
...node,
|
||||
selected: node.id === systemId,
|
||||
};
|
||||
}),
|
||||
);
|
||||
}, []);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ForwardedRef, useImperativeHandle } from 'react';
|
||||
import { ForwardedRef, useImperativeHandle, useRef } from 'react';
|
||||
import {
|
||||
CommandAddConnections,
|
||||
CommandAddSystems,
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
useMapInit,
|
||||
useMapRemoveSystems,
|
||||
useMapUpdateSystems,
|
||||
useCenterSystem,
|
||||
useSelectSystem,
|
||||
} from './api';
|
||||
import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
|
||||
@@ -35,8 +36,12 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
|
||||
const mapAddSystems = useMapAddSystems();
|
||||
const mapUpdateSystems = useMapUpdateSystems();
|
||||
const removeSystems = useMapRemoveSystems(onSelectionChange);
|
||||
const centerSystem = useCenterSystem();
|
||||
const selectSystem = useSelectSystem();
|
||||
|
||||
const selectRef = useRef({ onSelectionChange });
|
||||
selectRef.current = { onSelectionChange };
|
||||
|
||||
const { addConnections, removeConnections, updateConnection } = useCommandsConnections();
|
||||
const { mapUpdated, killsUpdated } = useMapCommands();
|
||||
const { charactersUpdated, presentCharacters, characterAdded, characterRemoved, characterUpdated } =
|
||||
@@ -91,14 +96,32 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
|
||||
killsUpdated(data as CommandKillsUpdated);
|
||||
break;
|
||||
|
||||
case Commands.centerSystem:
|
||||
setTimeout(() => {
|
||||
const systemId = `${data}`;
|
||||
centerSystem(systemId as CommandSelectSystem);
|
||||
}, 100);
|
||||
break;
|
||||
|
||||
case Commands.selectSystem:
|
||||
selectSystem(data as CommandSelectSystem);
|
||||
setTimeout(() => {
|
||||
const systemId = `${data}`;
|
||||
selectRef.current.onSelectionChange({
|
||||
systems: [systemId],
|
||||
connections: [],
|
||||
});
|
||||
selectSystem(systemId as CommandSelectSystem);
|
||||
}, 100);
|
||||
break;
|
||||
|
||||
case Commands.routes:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.linkSignatureToSystem:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn(`Map handlers: Unknown command: ${type}`, data);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
|
||||
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { CommandLinkSignatureToSystem } from '@/hooks/Mapper/types';
|
||||
import { SystemSignaturesContent } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignaturesContent';
|
||||
import {
|
||||
Setting,
|
||||
COSMIC_SIGNATURE,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatureSettingsDialog';
|
||||
|
||||
interface SystemLinkSignatureDialogProps {
|
||||
data: CommandLinkSignatureToSystem;
|
||||
setVisible: (visible: boolean) => void;
|
||||
}
|
||||
|
||||
const signatureSettings: Setting[] = [{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true }];
|
||||
|
||||
export const SystemLinkSignatureDialog = ({ data, setVisible }: SystemLinkSignatureDialogProps) => {
|
||||
const { outCommand } = useMapRootState();
|
||||
|
||||
const ref = useRef({ outCommand });
|
||||
ref.current = { outCommand };
|
||||
|
||||
const handleHide = useCallback(() => {
|
||||
setVisible(false);
|
||||
}, [setVisible]);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(signature: SystemSignature) => {
|
||||
if (!signature) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { outCommand } = ref.current;
|
||||
|
||||
outCommand({
|
||||
type: OutCommand.linkSignatureToSystem,
|
||||
data: {
|
||||
...data,
|
||||
signature_eve_id: signature.eve_id,
|
||||
},
|
||||
});
|
||||
setVisible(false);
|
||||
},
|
||||
[setVisible],
|
||||
);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
header="Select signature to link"
|
||||
visible
|
||||
draggable={false}
|
||||
style={{ width: '500px' }}
|
||||
onHide={handleHide}
|
||||
contentClassName="!p-0"
|
||||
>
|
||||
<SystemSignaturesContent
|
||||
systemId={`${data.solar_system_source}`}
|
||||
settings={signatureSettings}
|
||||
onSelect={handleSelect}
|
||||
selectable={true}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './SystemLinkSignatureDialog';
|
||||
@@ -90,7 +90,7 @@ export const SystemSettingsDialog = ({ systemId, visible, setVisible }: SystemSe
|
||||
}, []);
|
||||
|
||||
const handleInput = useCallback((e: any) => {
|
||||
e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '');
|
||||
e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9[\](){}]/g, '');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@@ -160,7 +160,7 @@ export const SystemSettingsDialog = ({ systemId, visible, setVisible }: SystemSe
|
||||
aria-describedby="label"
|
||||
autoComplete="off"
|
||||
value={label}
|
||||
maxLength={3}
|
||||
maxLength={5}
|
||||
onChange={e => setLabel(e.target.value)}
|
||||
onInput={handleInput}
|
||||
/>
|
||||
|
||||
@@ -2,3 +2,4 @@ export * from './Widget';
|
||||
export * from './WidgetsGrid';
|
||||
export * from './SystemSettingsDialog';
|
||||
export * from './SystemCustomLabelDialog';
|
||||
export * from './SystemLinkSignatureDialog';
|
||||
|
||||
@@ -91,7 +91,7 @@ export const RoutesList = ({ data, onContextMenu }: RoutesListProps) => {
|
||||
const { mapRef } = useMapRootState();
|
||||
|
||||
const handleClick = useCallback(
|
||||
(systemId: number) => mapRef.current?.command(Commands.selectSystem, systemId.toString()),
|
||||
(systemId: number) => mapRef.current?.command(Commands.centerSystem, systemId.toString()),
|
||||
[mapRef],
|
||||
);
|
||||
|
||||
|
||||
@@ -5,6 +5,14 @@ import { Checkbox } from 'primereact/checkbox';
|
||||
|
||||
export type Setting = { key: string; name: string; value: boolean };
|
||||
|
||||
export const COSMIC_SIGNATURE = 'Cosmic Signature';
|
||||
export const COSMIC_ANOMALY = 'Cosmic Anomaly';
|
||||
export const DEPLOYABLE = 'Deployable';
|
||||
export const STRUCTURE = 'Structure';
|
||||
export const STARBASE = 'Starbase';
|
||||
export const SHIP = 'Ship';
|
||||
export const DRONE = 'Drone';
|
||||
|
||||
interface SystemSignatureSettingsDialogProps {
|
||||
settings: Setting[];
|
||||
onSave: (settings: Setting[]) => void;
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import { Widget } from '@/hooks/Mapper/components/mapInterface/components';
|
||||
import { InfoDrawer, LayoutEventBlocker, TooltipPosition, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
|
||||
import { SystemSignaturesContent } from './SystemSignaturesContent';
|
||||
import { Setting, SystemSignatureSettingsDialog } from './SystemSignatureSettingsDialog';
|
||||
import {
|
||||
Setting,
|
||||
SystemSignatureSettingsDialog,
|
||||
COSMIC_SIGNATURE,
|
||||
COSMIC_ANOMALY,
|
||||
DEPLOYABLE,
|
||||
STRUCTURE,
|
||||
STARBASE,
|
||||
SHIP,
|
||||
DRONE,
|
||||
} from './SystemSignatureSettingsDialog';
|
||||
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
@@ -9,14 +19,6 @@ import { PrimeIcons } from 'primereact/api';
|
||||
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
export const COSMIC_SIGNATURE = 'Cosmic Signature';
|
||||
export const COSMIC_ANOMALY = 'Cosmic Anomaly';
|
||||
export const DEPLOYABLE = 'Deployable';
|
||||
export const STRUCTURE = 'Structure';
|
||||
export const STARBASE = 'Starbase';
|
||||
export const SHIP = 'Ship';
|
||||
export const DRONE = 'Drone';
|
||||
|
||||
const settings: Setting[] = [
|
||||
{ key: COSMIC_ANOMALY, name: 'Show Anomalies', value: true },
|
||||
{ key: COSMIC_SIGNATURE, name: 'Show Cosmic Signatures', value: true },
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
renderIcon,
|
||||
renderName,
|
||||
renderTimeLeft,
|
||||
renderLinkedSystem,
|
||||
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/renders';
|
||||
// import { PrimeIcons } from 'primereact/api';
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
@@ -41,8 +42,10 @@ const SORT_DEFAULT_VALUES: SystemSignaturesSortSettings = {
|
||||
interface SystemSignaturesContentProps {
|
||||
systemId: string;
|
||||
settings: Setting[];
|
||||
selectable?: boolean;
|
||||
onSelect?: (signature: SystemSignature) => void;
|
||||
}
|
||||
export const SystemSignaturesContent = ({ systemId, settings }: SystemSignaturesContentProps) => {
|
||||
export const SystemSignaturesContent = ({ systemId, settings, selectable, onSelect }: SystemSignaturesContentProps) => {
|
||||
const { outCommand } = useMapRootState();
|
||||
|
||||
const [signatures, setSignatures, signaturesRef] = useRefState<SystemSignature[]>([]);
|
||||
@@ -92,25 +95,25 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
setSignatures(signatures);
|
||||
}, [outCommand, systemId]);
|
||||
|
||||
const updateSignatures = useCallback(
|
||||
async (newSignatures: SystemSignature[], updateOnly: boolean) => {
|
||||
const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures, updateOnly);
|
||||
// const updateSignatures = useCallback(
|
||||
// async (newSignatures: SystemSignature[], updateOnly: boolean) => {
|
||||
// const { added, updated, removed } = getActualSigs(signaturesRef.current, newSignatures, updateOnly);
|
||||
|
||||
const { signatures: updatedSignatures } = await outCommand({
|
||||
type: OutCommand.updateSignatures,
|
||||
data: {
|
||||
system_id: systemId,
|
||||
added,
|
||||
updated,
|
||||
removed,
|
||||
},
|
||||
});
|
||||
// const { signatures: updatedSignatures } = await outCommand({
|
||||
// type: OutCommand.updateSignatures,
|
||||
// data: {
|
||||
// system_id: systemId,
|
||||
// added,
|
||||
// updated,
|
||||
// removed,
|
||||
// },
|
||||
// });
|
||||
|
||||
setSignatures(() => updatedSignatures);
|
||||
setSelectedSignatures([]);
|
||||
},
|
||||
[outCommand, systemId],
|
||||
);
|
||||
// setSignatures(() => updatedSignatures);
|
||||
// setSelectedSignatures([]);
|
||||
// },
|
||||
// [outCommand, systemId],
|
||||
// );
|
||||
|
||||
const handleUpdateSignatures = useCallback(
|
||||
async (newSignatures: SystemSignature[], updateOnly: boolean) => {
|
||||
@@ -133,6 +136,9 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
);
|
||||
|
||||
const handleDeleteSelected = useCallback(async () => {
|
||||
if (selectable) {
|
||||
return;
|
||||
}
|
||||
if (selectedSignatures.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -141,7 +147,7 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
signatures.filter(x => !selectedSignaturesEveIds.includes(x.eve_id)),
|
||||
false,
|
||||
);
|
||||
}, [handleUpdateSignatures, signatures, selectedSignatures]);
|
||||
}, [handleUpdateSignatures, selectable, signatures, selectedSignatures]);
|
||||
|
||||
const handleSelectAll = useCallback(() => {
|
||||
setSelectedSignatures(signatures);
|
||||
@@ -157,11 +163,26 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
setAskUser(false);
|
||||
}, [parsedSignatures, handleUpdateSignatures]);
|
||||
|
||||
const handleSelectSignatures = useCallback(
|
||||
e => {
|
||||
if (selectable) {
|
||||
onSelect?.(e.value);
|
||||
} else {
|
||||
setSelectedSignatures(e.value);
|
||||
}
|
||||
},
|
||||
[onSelect, selectable],
|
||||
);
|
||||
|
||||
useHotkey(true, ['a'], handleSelectAll);
|
||||
|
||||
useHotkey(false, ['Backspace', 'Delete'], handleDeleteSelected);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clipboardContent) {
|
||||
return;
|
||||
}
|
||||
@@ -179,7 +200,7 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
setParsedSignatures(newSignatures);
|
||||
setAskUser(true);
|
||||
}
|
||||
}, [clipboardContent]);
|
||||
}, [clipboardContent, selectable]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!systemId) {
|
||||
@@ -240,10 +261,10 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
className={classes.Table}
|
||||
value={filteredSignatures}
|
||||
size="small"
|
||||
selectionMode="multiple"
|
||||
selectionMode={selectable ? 'single' : 'multiple'}
|
||||
selection={selectedSignatures}
|
||||
metaKeySelection
|
||||
onSelectionChange={e => setSelectedSignatures(e.value)}
|
||||
onSelectionChange={handleSelectSignatures}
|
||||
dataKey="eve_id"
|
||||
tableClassName="w-full select-none"
|
||||
resizableColumns={false}
|
||||
@@ -297,6 +318,16 @@ export const SystemSignaturesContent = ({ systemId, settings }: SystemSignatures
|
||||
hidden={compact || medium}
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="linked_system"
|
||||
header="Linked System"
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
body={renderLinkedSystem}
|
||||
style={{ maxWidth: nameColumnWidth }}
|
||||
hidden={compact}
|
||||
sortable
|
||||
></Column>
|
||||
|
||||
<Column
|
||||
field="updated_at"
|
||||
header="Updated"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './renderIcon';
|
||||
export * from './renderName';
|
||||
export * from './renderTimeLeft';
|
||||
export * from './renderLinkedSystem';
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
import { SystemViewStandalone } from '@/hooks/Mapper/components/ui-kit';
|
||||
|
||||
export const renderLinkedSystem = (row: SystemSignature) => {
|
||||
if (!row.linked_system) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<span title={row.linked_system?.solar_system_name}>
|
||||
<SystemViewStandalone
|
||||
className={clsx('select-none text-center cursor-context-menu')}
|
||||
hideRegion
|
||||
{...row.linked_system}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
@@ -6,6 +6,7 @@ import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { OnTheMap, RightBar } from '@/hooks/Mapper/components/mapRootContent/components';
|
||||
import { MapContextMenu } from '@/hooks/Mapper/components/mapRootContent/components/MapContextMenu/MapContextMenu.tsx';
|
||||
import { useSkipContextMenu } from '@/hooks/Mapper/hooks/useSkipContextMenu';
|
||||
|
||||
export interface MapRootContentProps {}
|
||||
|
||||
@@ -19,6 +20,8 @@ export const MapRootContent = ({}: MapRootContentProps) => {
|
||||
|
||||
const handleShowOnTheMap = useCallback(() => setShowOnTheMap(true), []);
|
||||
|
||||
useSkipContextMenu();
|
||||
|
||||
return (
|
||||
<Layout map={<MapWrapper refn={mapRef} />}>
|
||||
{!isShowMenu ? (
|
||||
|
||||
@@ -22,6 +22,13 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
});
|
||||
}, [outCommand]);
|
||||
|
||||
const handleOpenUserSettings = useCallback(() => {
|
||||
outCommand({
|
||||
type: OutCommand.openUserSettings,
|
||||
data: null,
|
||||
});
|
||||
}, [outCommand]);
|
||||
|
||||
const toggleMinimap = useCallback(() => {
|
||||
setInterfaceSettings(x => ({
|
||||
...x,
|
||||
@@ -63,6 +70,16 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
|
||||
<WdTooltipWrapper content="User settings" 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={handleOpenUserSettings}
|
||||
>
|
||||
<i className="pi pi-cog text-lg"></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"
|
||||
@@ -87,9 +104,9 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
|
||||
onClick={toggleKSpace}
|
||||
>
|
||||
{interfaceSettings.isShowKSpace ? (
|
||||
<i className="pi pi-star-fill text-lg"></i>
|
||||
<i className="pi pi-heart-fill text-lg"></i>
|
||||
) : (
|
||||
<i className="pi pi-star text-lg"></i>
|
||||
<i className="pi pi-heart text-lg"></i>
|
||||
)}
|
||||
</button>
|
||||
</WdTooltipWrapper>
|
||||
|
||||
@@ -5,13 +5,20 @@ import { MapRootData, useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
|
||||
import isEqual from 'lodash.isequal';
|
||||
import { ContextMenuSystem, useContextMenuSystemHandlers } from '@/hooks/Mapper/components/contexts';
|
||||
import { SystemCustomLabelDialog, SystemSettingsDialog } from '@/hooks/Mapper/components/mapInterface/components';
|
||||
import {
|
||||
SystemCustomLabelDialog,
|
||||
SystemSettingsDialog,
|
||||
SystemLinkSignatureDialog,
|
||||
} from '@/hooks/Mapper/components/mapInterface/components';
|
||||
import classes from './MapWrapper.module.scss';
|
||||
import { Connections } from '@/hooks/Mapper/components/mapRootContent/components/Connections';
|
||||
import { ContextMenuSystemMultiple, useContextMenuSystemMultipleHandlers } from '../contexts/ContextMenuSystemMultiple';
|
||||
import { getSystemById } from '@/hooks/Mapper/helpers';
|
||||
import { Node } from 'reactflow';
|
||||
|
||||
import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { useMapEventListener } from '@/hooks/Mapper/events';
|
||||
|
||||
import { STORED_INTERFACE_DEFAULT_VALUES } from '@/hooks/Mapper/mapRootProvider/MapRootProvider';
|
||||
|
||||
interface MapWrapperProps {
|
||||
@@ -53,6 +60,7 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
|
||||
);
|
||||
|
||||
const [openSettings, setOpenSettings] = useState<string | null>(null);
|
||||
const [openLinkSignatures, setOpenLinkSignatures] = useState<any | null>(null);
|
||||
const [openCustomLabel, setOpenCustomLabel] = useState<string | null>(null);
|
||||
const handleCommand: OutCommandHandler = useCallback(
|
||||
event => {
|
||||
@@ -60,6 +68,9 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
|
||||
case OutCommand.openSettings:
|
||||
setOpenSettings(event.data.system_id);
|
||||
break;
|
||||
case OutCommand.linkSignatureToSystem:
|
||||
setOpenLinkSignatures(event.data);
|
||||
break;
|
||||
default:
|
||||
return outCommand(event);
|
||||
}
|
||||
@@ -88,6 +99,14 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
|
||||
|
||||
const handleConnectionDbClick = useCallback((e: SolarSystemConnection) => setSelectedConnection(e), []);
|
||||
|
||||
useMapEventListener(event => {
|
||||
switch (event.name) {
|
||||
case Commands.linkSignatureToSystem:
|
||||
setOpenLinkSignatures(event.data);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Map
|
||||
@@ -103,19 +122,15 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => {
|
||||
/>
|
||||
|
||||
{openSettings != null && (
|
||||
<SystemSettingsDialog
|
||||
systemId={openSettings}
|
||||
visible={openSettings != null}
|
||||
setVisible={() => setOpenSettings(null)}
|
||||
/>
|
||||
<SystemSettingsDialog systemId={openSettings} visible setVisible={() => setOpenSettings(null)} />
|
||||
)}
|
||||
|
||||
{openCustomLabel != null && (
|
||||
<SystemCustomLabelDialog
|
||||
systemId={openCustomLabel}
|
||||
visible={openCustomLabel != null}
|
||||
setVisible={() => setOpenCustomLabel(null)}
|
||||
/>
|
||||
<SystemCustomLabelDialog systemId={openCustomLabel} visible setVisible={() => setOpenCustomLabel(null)} />
|
||||
)}
|
||||
|
||||
{openLinkSignatures != null && (
|
||||
<SystemLinkSignatureDialog data={openLinkSignatures} setVisible={() => setOpenLinkSignatures(null)} />
|
||||
)}
|
||||
|
||||
<Connections selectedConnection={selectedConnection} onHide={() => setSelectedConnection(null)} />
|
||||
|
||||
@@ -37,7 +37,7 @@ export const CharacterCard = ({
|
||||
const { mapRef } = useMapRootState();
|
||||
|
||||
const handleSelect = useCallback(() => {
|
||||
mapRef.current?.command(Commands.selectSystem, char?.location?.solar_system_id?.toString());
|
||||
mapRef.current?.command(Commands.centerSystem, char?.location?.solar_system_id?.toString());
|
||||
}, [mapRef, char]);
|
||||
|
||||
return (
|
||||
|
||||
13
assets/js/hooks/Mapper/events/index.ts
Normal file
13
assets/js/hooks/Mapper/events/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createEvent } from 'react-event-hook';
|
||||
|
||||
export interface MapEvent {
|
||||
name: string;
|
||||
data: {
|
||||
solar_system_source: number;
|
||||
solar_system_target: number;
|
||||
};
|
||||
}
|
||||
|
||||
const { useMapEventListener, emitMapEvent } = createEvent('map-event')<MapEvent>();
|
||||
|
||||
export { useMapEventListener, emitMapEvent };
|
||||
@@ -1,4 +1,4 @@
|
||||
import { COSMIC_SIGNATURE } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures';
|
||||
import { COSMIC_SIGNATURE } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/SystemSignatureSettingsDialog';
|
||||
import { SystemSignature } from '@/hooks/Mapper/types';
|
||||
|
||||
export const parseSignatures = (value: string, availableKeys: string[]): SystemSignature[] => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './usePageVisibility';
|
||||
export * from './useClipboard';
|
||||
export * from './useHotkey';
|
||||
export * from './useSkipContextMenu';
|
||||
|
||||
15
assets/js/hooks/Mapper/hooks/useSkipContextMenu.ts
Normal file
15
assets/js/hooks/Mapper/hooks/useSkipContextMenu.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const useSkipContextMenu = () => {
|
||||
useEffect(() => {
|
||||
function handleContextMenu(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
window.addEventListener(`contextmenu`, handleContextMenu);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener(`contextmenu`, handleContextMenu);
|
||||
};
|
||||
}, []);
|
||||
};
|
||||
@@ -4,7 +4,6 @@ import { MapHandlers, MapUnionTypes, OutCommandHandler, SolarSystemConnection }
|
||||
import { useMapRootHandlers } from '@/hooks/Mapper/mapRootProvider/hooks';
|
||||
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import { DEFAULT_SETTINGS } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesProvider.tsx';
|
||||
|
||||
export type MapRootData = MapUnionTypes & {
|
||||
selectedSystems: string[];
|
||||
|
||||
@@ -27,6 +27,8 @@ import {
|
||||
useRoutes,
|
||||
} from './api';
|
||||
|
||||
import { emitMapEvent } from '@/hooks/Mapper/events';
|
||||
|
||||
export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
|
||||
const mapInit = useMapInit();
|
||||
const { addSystems, removeSystems, updateSystems } = useCommandsSystems();
|
||||
@@ -85,10 +87,18 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
|
||||
mapRoutes(data as CommandRoutes);
|
||||
break;
|
||||
|
||||
case Commands.centerSystem:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.selectSystem:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
case Commands.linkSignatureToSystem:
|
||||
emitMapEvent({ name: Commands.linkSignatureToSystem, data });
|
||||
break;
|
||||
|
||||
case Commands.killsUpdated:
|
||||
// do nothing here
|
||||
break;
|
||||
|
||||
@@ -21,7 +21,9 @@ export enum Commands {
|
||||
mapUpdated = 'map_updated',
|
||||
killsUpdated = 'kills_updated',
|
||||
routes = 'routes',
|
||||
centerSystem = 'center_system',
|
||||
selectSystem = 'select_system',
|
||||
linkSignatureToSystem = 'link_signature_to_system',
|
||||
}
|
||||
|
||||
export type Command =
|
||||
@@ -40,7 +42,9 @@ export type Command =
|
||||
| Commands.mapUpdated
|
||||
| Commands.killsUpdated
|
||||
| Commands.routes
|
||||
| Commands.selectSystem;
|
||||
| Commands.selectSystem
|
||||
| Commands.centerSystem
|
||||
| Commands.linkSignatureToSystem;
|
||||
|
||||
export type CommandInit = {
|
||||
systems: SolarSystemRawType[];
|
||||
@@ -72,6 +76,12 @@ export type CommandMapUpdated = Partial<CommandInit>;
|
||||
export type CommandRoutes = RoutesList;
|
||||
export type CommandKillsUpdated = Kill[];
|
||||
export type CommandSelectSystem = string | undefined;
|
||||
export type CommandCenterSystem = string | undefined;
|
||||
export type CommandLinkSignatureToSystem = {
|
||||
solar_system_source: number;
|
||||
solar_system_target: number;
|
||||
signatures: any[];
|
||||
};
|
||||
|
||||
export interface CommandData {
|
||||
[Commands.init]: CommandInit;
|
||||
@@ -90,6 +100,8 @@ export interface CommandData {
|
||||
[Commands.routes]: CommandRoutes;
|
||||
[Commands.killsUpdated]: CommandKillsUpdated;
|
||||
[Commands.selectSystem]: CommandSelectSystem;
|
||||
[Commands.centerSystem]: CommandCenterSystem;
|
||||
[Commands.linkSignatureToSystem]: CommandLinkSignatureToSystem;
|
||||
}
|
||||
|
||||
export interface MapHandlers {
|
||||
@@ -123,7 +135,9 @@ export enum OutCommand {
|
||||
setAutopilotWaypoint = 'set_autopilot_waypoint',
|
||||
addSystem = 'add_system',
|
||||
addCharacter = 'add_character',
|
||||
openUserSettings = 'open_user_settings',
|
||||
getPassages = 'get_passages',
|
||||
linkSignatureToSystem = 'link_signature_to_system',
|
||||
|
||||
// Only UI commands
|
||||
openSettings = 'open_settings',
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types';
|
||||
|
||||
export type SystemSignature = {
|
||||
eve_id: string;
|
||||
kind: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
group: string;
|
||||
linked_system?: SolarSystemStaticInfoRaw;
|
||||
updated_at?: string;
|
||||
};
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"primeicons": "^7.0.0",
|
||||
"primereact": "^10.6.5",
|
||||
"react-error-boundary": "^4.0.13",
|
||||
"react-event-hook": "^3.1.2",
|
||||
"react-flow-renderer": "^10.3.17",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-usestateref": "^1.0.9",
|
||||
|
||||
@@ -3199,6 +3199,11 @@ react-error-boundary@^4.0.13:
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
|
||||
react-event-hook@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/react-event-hook/-/react-event-hook-3.1.2.tgz#445e8f3b751f6abe4ef199f31bff47593c4c13d4"
|
||||
integrity sha512-qQ9LXLdxmWRRZPlnqVjqlw7jovSvDosQEOyQ9cjPHhtDv8JIszjj0td1PuHJHrVW0LS8a1XeJhLe6i7S5u9SbQ==
|
||||
|
||||
react-flow-renderer@^10.3.17:
|
||||
version "10.3.17"
|
||||
resolved "https://registry.npmjs.org/react-flow-renderer/-/react-flow-renderer-10.3.17.tgz"
|
||||
|
||||
@@ -19,6 +19,7 @@ defmodule WandererApp.Api do
|
||||
resource WandererApp.Api.MapCharacterSettings
|
||||
resource WandererApp.Api.MapSubscription
|
||||
resource WandererApp.Api.MapTransaction
|
||||
resource WandererApp.Api.MapUserSettings
|
||||
resource WandererApp.Api.User
|
||||
resource WandererApp.Api.ShipTypeInfo
|
||||
resource WandererApp.Api.UserActivity
|
||||
|
||||
@@ -14,6 +14,7 @@ defmodule WandererApp.Api.MapSystemSignature do
|
||||
define(:all_active, action: :all_active)
|
||||
define(:create, action: :create)
|
||||
define(:update, action: :update)
|
||||
define(:update_linked_system, action: :update_linked_system)
|
||||
|
||||
define(:by_id,
|
||||
get_by: [:id],
|
||||
@@ -66,13 +67,18 @@ defmodule WandererApp.Api.MapSystemSignature do
|
||||
:name,
|
||||
:description,
|
||||
:kind,
|
||||
:group
|
||||
:group,
|
||||
:linked_system_id
|
||||
]
|
||||
|
||||
primary? true
|
||||
require_atomic? false
|
||||
end
|
||||
|
||||
update :update_linked_system do
|
||||
accept [:linked_system_id]
|
||||
end
|
||||
|
||||
read :by_system_id do
|
||||
argument(:system_id, :string, allow_nil?: false)
|
||||
|
||||
@@ -99,6 +105,10 @@ defmodule WandererApp.Api.MapSystemSignature do
|
||||
allow_nil? true
|
||||
end
|
||||
|
||||
attribute :linked_system_id, :integer do
|
||||
allow_nil? true
|
||||
end
|
||||
|
||||
attribute :kind, :string
|
||||
attribute :group, :string
|
||||
|
||||
|
||||
54
lib/wanderer_app/api/map_user_settings.ex
Normal file
54
lib/wanderer_app/api/map_user_settings.ex
Normal file
@@ -0,0 +1,54 @@
|
||||
defmodule WandererApp.Api.MapUserSettings do
|
||||
@moduledoc false
|
||||
|
||||
use Ash.Resource,
|
||||
domain: WandererApp.Api,
|
||||
data_layer: AshPostgres.DataLayer
|
||||
|
||||
postgres do
|
||||
repo(WandererApp.Repo)
|
||||
table("map_user_settings_v1")
|
||||
end
|
||||
|
||||
code_interface do
|
||||
define(:create, action: :create)
|
||||
|
||||
define(:by_user_id,
|
||||
get_by: [:map_id, :user_id],
|
||||
action: :read
|
||||
)
|
||||
|
||||
define(:update_settings, action: :update_settings)
|
||||
end
|
||||
|
||||
actions do
|
||||
default_accept [
|
||||
:map_id,
|
||||
:user_id,
|
||||
:settings
|
||||
]
|
||||
|
||||
defaults [:create, :read, :update, :destroy]
|
||||
|
||||
update :update_settings do
|
||||
accept [:settings]
|
||||
end
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key :id
|
||||
|
||||
attribute :settings, :string do
|
||||
allow_nil? true
|
||||
end
|
||||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :map, WandererApp.Api.Map, primary_key?: true, allow_nil?: false
|
||||
belongs_to :user, WandererApp.Api.User, primary_key?: true, allow_nil?: false
|
||||
end
|
||||
|
||||
identities do
|
||||
identity :uniq_map_user, [:map_id, :user_id]
|
||||
end
|
||||
end
|
||||
@@ -6,7 +6,7 @@ defmodule WandererApp.Character do
|
||||
@read_character_wallet_scope "esi-wallet.read_character_wallet.v1"
|
||||
@read_corp_wallet_scope "esi-wallet.read_corporation_wallets.v1"
|
||||
|
||||
def get_character(character_id) do
|
||||
def get_character(character_id) when not is_nil(character_id) do
|
||||
case Cachex.get(:character_cache, character_id) do
|
||||
{:ok, nil} ->
|
||||
case WandererApp.Api.Character.by_id(character_id) do
|
||||
@@ -23,6 +23,8 @@ defmodule WandererApp.Character do
|
||||
end
|
||||
end
|
||||
|
||||
def get_character(_character_id), do: {:ok, nil}
|
||||
|
||||
def get_character!(character_id) do
|
||||
case get_character(character_id) do
|
||||
{:ok, character} ->
|
||||
|
||||
@@ -56,9 +56,9 @@ defmodule WandererApp.Map do
|
||||
map
|
||||
|> Map.get(:options)
|
||||
|> case do
|
||||
nil -> %{"layout" => "left_to_right"}
|
||||
options -> Jason.decode!(options)
|
||||
end
|
||||
nil -> %{"layout" => "left_to_right"}
|
||||
options -> Jason.decode!(options)
|
||||
end
|
||||
end
|
||||
|
||||
def update_map(map_id, map_update) do
|
||||
|
||||
@@ -856,10 +856,9 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
location.solar_system_id
|
||||
) do
|
||||
true ->
|
||||
{:ok, character} = WandererApp.Character.get_character(character_id)
|
||||
:ok = maybe_add_system(map_id, location, old_location, rtree_name, map_opts)
|
||||
:ok = maybe_add_system(map_id, old_location, location, rtree_name, map_opts)
|
||||
:ok = maybe_add_connection(map_id, location, old_location, character)
|
||||
:ok = maybe_add_connection(map_id, location, old_location, character_id)
|
||||
|
||||
_ ->
|
||||
:ok
|
||||
@@ -1590,26 +1589,33 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
|
||||
defp maybe_remove_connection(_map_id, _location, _old_location), do: :ok
|
||||
|
||||
defp maybe_add_connection(map_id, location, old_location, character)
|
||||
defp maybe_add_connection(map_id, location, old_location, character_id)
|
||||
when not is_nil(location) and not is_nil(old_location) and
|
||||
not is_nil(old_location.solar_system_id) and
|
||||
location.solar_system_id != old_location.solar_system_id do
|
||||
case character do
|
||||
character_id
|
||||
|> WandererApp.Character.get_character!()
|
||||
|> case do
|
||||
nil ->
|
||||
:ok
|
||||
|
||||
_ ->
|
||||
character ->
|
||||
:telemetry.execute([:wanderer_app, :map, :character, :jump], %{count: 1}, %{})
|
||||
|
||||
{:ok, _} =
|
||||
WandererApp.Api.MapChainPassages.new(%{
|
||||
map_id: map_id,
|
||||
character_id: character.id,
|
||||
character_id: character_id,
|
||||
ship_type_id: character.ship,
|
||||
ship_name: character.ship_name,
|
||||
solar_system_source_id: old_location.solar_system_id,
|
||||
solar_system_target_id: location.solar_system_id
|
||||
})
|
||||
|
||||
broadcast!(map_id, :maybe_select_system, %{
|
||||
character_id: character_id,
|
||||
solar_system_id: location.solar_system_id
|
||||
})
|
||||
end
|
||||
|
||||
case WandererApp.Map.check_connection(map_id, location, old_location) do
|
||||
@@ -1621,16 +1627,24 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
solar_system_target: location.solar_system_id
|
||||
})
|
||||
|
||||
broadcast!(map_id, :add_connection, connection)
|
||||
WandererApp.Map.add_connection(map_id, connection)
|
||||
|
||||
broadcast!(map_id, :add_connection, connection)
|
||||
broadcast!(map_id, :maybe_link_signature, %{
|
||||
character_id: character_id,
|
||||
solar_system_source: old_location.solar_system_id,
|
||||
solar_system_target: location.solar_system_id,
|
||||
})
|
||||
|
||||
:ok
|
||||
|
||||
{:error, error} ->
|
||||
@logger.debug(fn -> "Failed to add connection: #{inspect(error, pretty: true)}" end)
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_add_connection(_map_id, _location, _old_location, _character), do: :ok
|
||||
defp maybe_add_connection(_map_id, _location, _old_location, _character_id), do: :ok
|
||||
|
||||
defp maybe_add_system(map_id, location, old_location, rtree_name, opts)
|
||||
when not is_nil(location) do
|
||||
@@ -1710,10 +1724,10 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
|
||||
defp calc_new_system_position(map_id, old_location, rtree_name, opts),
|
||||
do:
|
||||
{:ok,
|
||||
map_id
|
||||
|> WandererApp.Map.find_system_by_location(old_location)
|
||||
|> WandererApp.Map.PositionCalculator.get_new_system_position(rtree_name, opts)}
|
||||
{:ok,
|
||||
map_id
|
||||
|> WandererApp.Map.find_system_by_location(old_location)
|
||||
|> WandererApp.Map.PositionCalculator.get_new_system_position(rtree_name, opts)}
|
||||
|
||||
defp _broadcast_acl_updates(
|
||||
{:ok,
|
||||
|
||||
49
lib/wanderer_app/repositories/map_user_settings_repo.ex
Normal file
49
lib/wanderer_app/repositories/map_user_settings_repo.ex
Normal file
@@ -0,0 +1,49 @@
|
||||
defmodule WandererApp.MapUserSettingsRepo do
|
||||
use WandererApp, :repository
|
||||
|
||||
@default_form_data %{"select_on_spash" => "false", "link_signature_on_splash" => "false"}
|
||||
|
||||
def get(map_id, user_id) do
|
||||
map_id
|
||||
|> WandererApp.Api.MapUserSettings.by_user_id(user_id)
|
||||
|> case do
|
||||
{:ok, settings} ->
|
||||
{:ok, settings}
|
||||
|
||||
_ ->
|
||||
{:ok, nil}
|
||||
end
|
||||
end
|
||||
|
||||
def get!(map_id, user_id) do
|
||||
WandererApp.Api.MapUserSettings.by_user_id(map_id, user_id)
|
||||
|> case do
|
||||
{:ok, user_settings} -> user_settings
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
def create_or_update(map_id, user_id, settings) do
|
||||
get!(map_id, user_id)
|
||||
|> case do
|
||||
user_settings when not is_nil(user_settings) ->
|
||||
user_settings
|
||||
|> WandererApp.Api.MapUserSettings.update_settings(%{settings: settings})
|
||||
|
||||
_ ->
|
||||
WandererApp.Api.MapUserSettings.create(%{
|
||||
map_id: map_id,
|
||||
user_id: user_id,
|
||||
settings: settings
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
def to_form_data(nil), do: {:ok, @default_form_data}
|
||||
def to_form_data(%{settings: settings} = _user_settings), do: {:ok, Jason.decode!(settings)}
|
||||
|
||||
def to_form_data!(user_settings) do
|
||||
{:ok, data} = to_form_data(user_settings)
|
||||
data
|
||||
end
|
||||
end
|
||||
@@ -377,7 +377,7 @@ defmodule WandererAppWeb.CoreComponents do
|
||||
|
||||
~H"""
|
||||
<div phx-feedback-for={@name} class="form-control mt-8">
|
||||
<label class="label cursor-pointer">
|
||||
<label class="label cursor-pointer gap-2">
|
||||
<span class="label-text"><%= @label %></span>
|
||||
<input type="hidden" name={@name} value="false" />
|
||||
<input
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<main class="bg-gradient-to-r from-stone-950 to-stone-900">
|
||||
<main class="bg-stone-950">
|
||||
<%= @inner_content %>
|
||||
</main>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<main
|
||||
class="main flex-col !min-h-screen justify-between flex z-0 focus:outline-none transition-all duration-500 opacity-0 phx-page-loading:opacity-0 bg-gradient-to-r from-stone-950 to-stone-900 ccp-font"
|
||||
class="main flex-col !min-h-screen justify-between flex z-0 focus:outline-none transition-all duration-500 opacity-0 phx-page-loading:opacity-0 bg-stone-950 ccp-font"
|
||||
phx-mounted={JS.remove_class("opacity-0")}
|
||||
>
|
||||
<navbar class="navbar bg-base-100 !sticky top-0 z-50 bg-opacity-0 ">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</.connection_status>
|
||||
|
||||
<main
|
||||
class="main flex-1 relative z-0 overflow-hidden focus:outline-none transition-all duration-500 opacity-0 phx-page-loading:opacity-0 bg-gradient-to-r from-stone-950 to-stone-900 maps_bg ccp-font"
|
||||
class="main flex-1 relative z-0 overflow-hidden focus:outline-none transition-all duration-500 opacity-0 phx-page-loading:opacity-0 bg-stone-950 maps_bg ccp-font"
|
||||
phx-mounted={JS.remove_class("opacity-0")}
|
||||
>
|
||||
<%= @inner_content %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="flex flex-col w-0 flex-1 overflow-hidden bg-gradient-to-r from-stone-950 to-stone-900">
|
||||
<div class="flex flex-col w-0 flex-1 overflow-hidden bg-stone-950">
|
||||
<.connection_status>
|
||||
Re-establishing connection...
|
||||
</.connection_status>
|
||||
|
||||
@@ -319,7 +319,6 @@ defmodule WandererAppWeb.AccessListsLive do
|
||||
|
||||
@impl true
|
||||
def handle_info({:search, text}, socket) do
|
||||
|
||||
active_character_id =
|
||||
socket.assigns.current_user.characters
|
||||
|> Enum.filter(fn character -> not is_nil(character.refresh_token) end)
|
||||
|
||||
@@ -113,45 +113,45 @@ defmodule WandererAppWeb.MapLive do
|
||||
}
|
||||
} = socket
|
||||
) do
|
||||
_on_map_started(map_id, current_user, user_permissions)
|
||||
on_map_started(map_id, current_user, user_permissions)
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:character_token_invalid, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> _put_invalid_token_message()}
|
||||
end
|
||||
def handle_info(:character_token_invalid, socket),
|
||||
do:
|
||||
{:noreply,
|
||||
socket
|
||||
|> _put_invalid_token_message()}
|
||||
|
||||
@impl true
|
||||
def handle_info(%{event: :add_system, payload: system}, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> push_map_event("add_systems", [map_ui_system(system)])}
|
||||
end
|
||||
def handle_info(%{event: :add_system, payload: system}, socket),
|
||||
do:
|
||||
{:noreply,
|
||||
socket
|
||||
|> push_map_event("add_systems", [map_ui_system(system)])}
|
||||
|
||||
@impl true
|
||||
def handle_info(%{event: :update_system, payload: system}, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> push_map_event("update_systems", [map_ui_system(system)])}
|
||||
end
|
||||
def handle_info(%{event: :update_system, payload: system}, socket),
|
||||
do:
|
||||
{:noreply,
|
||||
socket
|
||||
|> push_map_event("update_systems", [map_ui_system(system)])}
|
||||
|
||||
@impl true
|
||||
def handle_info(%{event: :update_connection, payload: connection}, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> push_map_event("update_connection", map_ui_connection(connection))}
|
||||
end
|
||||
def handle_info(%{event: :update_connection, payload: connection}, socket),
|
||||
do:
|
||||
{:noreply,
|
||||
socket
|
||||
|> push_map_event("update_connection", map_ui_connection(connection))}
|
||||
|
||||
@impl true
|
||||
def handle_info(%{event: :systems_removed, payload: solar_system_ids}, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> push_map_event("remove_systems", solar_system_ids)}
|
||||
end
|
||||
def handle_info(%{event: :systems_removed, payload: solar_system_ids}, socket),
|
||||
do:
|
||||
{:noreply,
|
||||
socket
|
||||
|> push_map_event("remove_systems", solar_system_ids)}
|
||||
|
||||
@impl true
|
||||
def handle_info(%{event: :remove_connections, payload: connections}, socket) do
|
||||
@@ -177,6 +177,101 @@ defmodule WandererAppWeb.MapLive do
|
||||
)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(
|
||||
%{
|
||||
event: :maybe_select_system,
|
||||
payload: %{
|
||||
character_id: character_id,
|
||||
solar_system_id: solar_system_id
|
||||
}
|
||||
},
|
||||
%{assigns: %{current_user: current_user, map_user_settings: map_user_settings}} = socket
|
||||
) do
|
||||
is_user_character? =
|
||||
current_user.characters |> Enum.map(& &1.id) |> Enum.member?(character_id)
|
||||
|
||||
select_on_spash? =
|
||||
map_user_settings
|
||||
|> WandererApp.MapUserSettingsRepo.to_form_data!()
|
||||
|> Map.get("select_on_spash", "false")
|
||||
|> String.to_existing_atom()
|
||||
|
||||
socket =
|
||||
(is_user_character? && select_on_spash?)
|
||||
|> case do
|
||||
true ->
|
||||
socket
|
||||
|> push_map_event("select_system", solar_system_id)
|
||||
|
||||
false ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(
|
||||
%{
|
||||
event: :maybe_link_signature,
|
||||
payload: %{
|
||||
character_id: character_id,
|
||||
solar_system_source: solar_system_source,
|
||||
solar_system_target: solar_system_target,
|
||||
}
|
||||
},
|
||||
%{assigns: %{current_user: current_user, map_id: map_id, map_user_settings: map_user_settings}} = socket
|
||||
) do
|
||||
is_user_character? =
|
||||
current_user.characters |> Enum.map(& &1.id) |> Enum.member?(character_id)
|
||||
|
||||
link_signature_on_splash? =
|
||||
map_user_settings
|
||||
|> WandererApp.MapUserSettingsRepo.to_form_data!()
|
||||
|> Map.get("link_signature_on_splash", "false")
|
||||
|> String.to_existing_atom()
|
||||
|
||||
{:ok, signatures} =
|
||||
WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{
|
||||
map_id: map_id,
|
||||
solar_system_id: solar_system_source
|
||||
})
|
||||
|> case do
|
||||
{:ok, system} ->
|
||||
{:ok, get_system_signatures(system.id)}
|
||||
_ ->
|
||||
{:ok, []}
|
||||
end
|
||||
|
||||
# signatures
|
||||
# :
|
||||
# (4) [{…}, {…}, {…}, {…}]
|
||||
# solar_system_source
|
||||
# :
|
||||
# 31000526
|
||||
# solar_system_target
|
||||
# :
|
||||
# 31001819
|
||||
#
|
||||
socket =
|
||||
(is_user_character? && link_signature_on_splash? && not(signatures |> Enum.empty?()))
|
||||
|> case do
|
||||
true ->
|
||||
socket
|
||||
|> push_map_event("link_signature_to_system", %{
|
||||
solar_system_source: solar_system_source,
|
||||
solar_system_target: solar_system_target,
|
||||
signatures: signatures
|
||||
})
|
||||
|
||||
false ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(%{event: :update_map, payload: map_diff}, socket) do
|
||||
{:noreply,
|
||||
@@ -420,6 +515,7 @@ defmodule WandererAppWeb.MapLive do
|
||||
{:map_start,
|
||||
%{
|
||||
map_id: map_id,
|
||||
map_user_settings: map_user_settings,
|
||||
user_characters: user_character_eve_ids,
|
||||
initial_data: initial_data,
|
||||
events: events
|
||||
@@ -466,20 +562,24 @@ defmodule WandererAppWeb.MapLive do
|
||||
{:map_loaded,
|
||||
%{
|
||||
map_id: map_id,
|
||||
user_characters: user_character_eve_ids,
|
||||
initial_data: initial_data
|
||||
}},
|
||||
10
|
||||
)
|
||||
|
||||
{:noreply, socket}
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(
|
||||
map_user_settings: map_user_settings,
|
||||
user_characters: user_character_eve_ids,
|
||||
has_tracked_characters?: _has_tracked_characters?(user_character_eve_ids)
|
||||
)}
|
||||
end
|
||||
|
||||
def handle_info(
|
||||
{:map_loaded,
|
||||
%{
|
||||
map_id: map_id,
|
||||
user_characters: user_character_eve_ids,
|
||||
initial_data: initial_data
|
||||
} = _loaded_data},
|
||||
socket
|
||||
@@ -488,11 +588,7 @@ defmodule WandererAppWeb.MapLive do
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(
|
||||
map_loaded?: true,
|
||||
user_characters: user_character_eve_ids,
|
||||
has_tracked_characters?: _has_tracked_characters?(user_character_eve_ids)
|
||||
)
|
||||
|> assign(map_loaded?: true)
|
||||
|> push_map_event(
|
||||
"init",
|
||||
initial_data |> Map.put(:characters, map_characters |> Enum.map(&map_ui_character/1))
|
||||
@@ -1013,7 +1109,7 @@ defmodule WandererAppWeb.MapLive do
|
||||
s |> WandererApp.Api.MapSystemSignature.create!()
|
||||
end)
|
||||
|
||||
{:reply, %{signatures: _get_system_signatures(system.id)}, socket}
|
||||
{:reply, %{signatures: get_system_signatures(system.id)}, socket}
|
||||
|
||||
_ ->
|
||||
{:reply, %{signatures: []},
|
||||
@@ -1044,7 +1140,7 @@ defmodule WandererAppWeb.MapLive do
|
||||
solar_system_id: solar_system_id |> String.to_integer()
|
||||
}) do
|
||||
{:ok, system} ->
|
||||
{:reply, %{signatures: _get_system_signatures(system.id)}, socket}
|
||||
{:reply, %{signatures: get_system_signatures(system.id)}, socket}
|
||||
|
||||
_ ->
|
||||
{:reply, %{signatures: []}, socket}
|
||||
@@ -1472,7 +1568,89 @@ defmodule WandererAppWeb.MapLive do
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("noop", _, socket), do: {:noreply, socket}
|
||||
def handle_event(
|
||||
"open_user_settings",
|
||||
_,
|
||||
%{assigns: %{map_id: map_id, current_user: current_user}} = socket
|
||||
) do
|
||||
{:ok, user_settings_form} =
|
||||
WandererApp.MapUserSettingsRepo.get!(map_id, current_user.id)
|
||||
|> WandererApp.MapUserSettingsRepo.to_form_data()
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(
|
||||
show_user_settings?: true,
|
||||
user_settings_form: user_settings_form |> to_form()
|
||||
)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event(
|
||||
"update_user_settings",
|
||||
user_settings_form,
|
||||
%{assigns: %{map_id: map_id, current_user: current_user}} = socket
|
||||
) do
|
||||
settings = user_settings_form |> Map.take(["select_on_spash", "link_signature_on_splash"]) |> Jason.encode!()
|
||||
|
||||
{:ok, user_settings} =
|
||||
WandererApp.MapUserSettingsRepo.create_or_update(map_id, current_user.id, settings)
|
||||
|
||||
{:noreply,
|
||||
socket |> assign(user_settings_form: user_settings_form, map_user_settings: user_settings)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event(
|
||||
"link_signature_to_system",
|
||||
%{
|
||||
"signature_eve_id" => signature_eve_id,
|
||||
"solar_system_source" => solar_system_source,
|
||||
"solar_system_target" => solar_system_target
|
||||
},
|
||||
socket
|
||||
) do
|
||||
|
||||
socket
|
||||
|> _check_user_permissions(:update_system)
|
||||
|> case do
|
||||
true ->
|
||||
case WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{
|
||||
map_id: socket.assigns.map_id,
|
||||
solar_system_id: solar_system_source
|
||||
}) do
|
||||
{:ok, system} ->
|
||||
first_character_eve_id =
|
||||
Map.get(socket.assigns, :user_characters, []) |> List.first()
|
||||
|
||||
case not is_nil(first_character_eve_id) do
|
||||
true ->
|
||||
WandererApp.Api.MapSystemSignature.by_system_id!(system.id)
|
||||
|> Enum.filter(fn s -> s.eve_id == signature_eve_id end)
|
||||
|> Enum.each(fn s ->
|
||||
s
|
||||
|> WandererApp.Api.MapSystemSignature.update_linked_system(%{linked_system_id: solar_system_target})
|
||||
end)
|
||||
|
||||
{:noreply, socket}
|
||||
|
||||
_ ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(
|
||||
:error,
|
||||
"You should enable tracking for at least one character to work with signatures."
|
||||
)}
|
||||
end
|
||||
|
||||
_ ->
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
_ ->
|
||||
{:noreply, socket}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("show_activity", _, socket) do
|
||||
@@ -1495,6 +1673,10 @@ defmodule WandererAppWeb.MapLive do
|
||||
def handle_event("hide_tracking", _, socket),
|
||||
do: {:noreply, socket |> assign(show_tracking?: false)}
|
||||
|
||||
@impl true
|
||||
def handle_event("hide_user_settings", _, socket),
|
||||
do: {:noreply, socket |> assign(show_user_settings?: false)}
|
||||
|
||||
@impl true
|
||||
def handle_event(
|
||||
"log_map_error",
|
||||
@@ -1513,112 +1695,119 @@ defmodule WandererAppWeb.MapLive do
|
||||
})}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("noop", _, socket), do: {:noreply, socket}
|
||||
|
||||
@impl true
|
||||
def handle_event(event, body, socket) do
|
||||
Logger.warning(fn -> "unhandled event: #{event} #{inspect(body)}" end)
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
defp _on_map_started(map_id, current_user, user_permissions) do
|
||||
case user_permissions do
|
||||
%{view_system: true, track_character: track_character} ->
|
||||
{:ok, _} = current_user |> WandererApp.Api.User.update_last_map(%{last_map_id: map_id})
|
||||
defp on_map_started(
|
||||
map_id,
|
||||
current_user,
|
||||
%{view_system: true, track_character: track_character} = user_permissions
|
||||
) do
|
||||
with {:ok, _} <- current_user |> WandererApp.Api.User.update_last_map(%{last_map_id: map_id}),
|
||||
{:ok, map_user_settings} <- WandererApp.MapUserSettingsRepo.get(map_id, current_user.id),
|
||||
{:ok, tracked_map_characters} <- _get_tracked_map_characters(map_id, current_user),
|
||||
{:ok, characters_limit} <- map_id |> WandererApp.Map.get_characters_limit(),
|
||||
{:ok, present_character_ids} <-
|
||||
WandererApp.Cache.lookup("map_#{map_id}:presence_character_ids", []),
|
||||
{:ok, kills} <- WandererApp.Cache.lookup("map_#{map_id}:zkb_kills", Map.new()) do
|
||||
user_character_eve_ids = tracked_map_characters |> Enum.map(& &1.eve_id)
|
||||
|
||||
{:ok, tracked_map_characters} = _get_tracked_map_characters(map_id, current_user)
|
||||
events =
|
||||
case tracked_map_characters |> Enum.any?(&(&1.access_token == nil)) do
|
||||
true ->
|
||||
[:invalid_token_message]
|
||||
|
||||
user_character_eve_ids = tracked_map_characters |> Enum.map(& &1.eve_id)
|
||||
_ ->
|
||||
[]
|
||||
end
|
||||
|
||||
events =
|
||||
case tracked_map_characters |> Enum.any?(&(&1.access_token == nil)) do
|
||||
true ->
|
||||
[:invalid_token_message]
|
||||
events =
|
||||
case tracked_map_characters |> Enum.empty?() do
|
||||
true ->
|
||||
events ++ [:empty_tracked_characters]
|
||||
|
||||
_ ->
|
||||
[]
|
||||
end
|
||||
_ ->
|
||||
events
|
||||
end
|
||||
|
||||
events =
|
||||
case tracked_map_characters |> Enum.empty?() do
|
||||
true ->
|
||||
events ++ [:empty_tracked_characters]
|
||||
events =
|
||||
case present_character_ids |> Enum.count() < characters_limit do
|
||||
true ->
|
||||
events ++ [{:track_characters, tracked_map_characters, track_character}]
|
||||
|
||||
_ ->
|
||||
events
|
||||
end
|
||||
_ ->
|
||||
events ++ [:map_character_limit]
|
||||
end
|
||||
|
||||
{:ok, characters_limit} = map_id |> WandererApp.Map.get_characters_limit()
|
||||
initial_data =
|
||||
map_id
|
||||
|> _get_map_data()
|
||||
|> Map.merge(%{
|
||||
kills:
|
||||
kills
|
||||
|> Enum.filter(fn {_, kills} -> kills > 0 end)
|
||||
|> Enum.map(&map_ui_kill/1),
|
||||
present_characters:
|
||||
present_character_ids
|
||||
|> WandererApp.Character.get_character_eve_ids!(),
|
||||
user_characters: user_character_eve_ids,
|
||||
user_permissions: user_permissions,
|
||||
system_static_infos: nil,
|
||||
wormhole_types: nil,
|
||||
effects: nil,
|
||||
reset: false
|
||||
})
|
||||
|
||||
{:ok, present_character_ids} =
|
||||
WandererApp.Cache.lookup("map_#{map_id}:presence_character_ids", [])
|
||||
system_static_infos =
|
||||
map_id
|
||||
|> WandererApp.Map.list_systems!()
|
||||
|> Enum.map(&WandererApp.CachedInfo.get_system_static_info!(&1.solar_system_id))
|
||||
|> Enum.map(&map_ui_system_static_info/1)
|
||||
|
||||
events =
|
||||
case present_character_ids |> Enum.count() < characters_limit do
|
||||
true ->
|
||||
events ++ [{:track_characters, tracked_map_characters, track_character}]
|
||||
|
||||
_ ->
|
||||
events ++ [:map_character_limit]
|
||||
end
|
||||
|
||||
{:ok, kills} = WandererApp.Cache.lookup("map_#{map_id}:zkb_kills", Map.new())
|
||||
|
||||
initial_data =
|
||||
map_id
|
||||
|> _get_map_data()
|
||||
|> Map.merge(%{
|
||||
kills:
|
||||
kills
|
||||
|> Enum.filter(fn {_, kills} -> kills > 0 end)
|
||||
|> Enum.map(&map_ui_kill/1),
|
||||
present_characters:
|
||||
present_character_ids
|
||||
|> WandererApp.Character.get_character_eve_ids!(),
|
||||
user_characters: user_character_eve_ids,
|
||||
user_permissions: user_permissions,
|
||||
system_static_infos: nil,
|
||||
wormhole_types: nil,
|
||||
effects: nil,
|
||||
reset: false
|
||||
})
|
||||
|
||||
system_static_infos =
|
||||
map_id
|
||||
|> WandererApp.Map.list_systems!()
|
||||
|> Enum.map(&WandererApp.CachedInfo.get_system_static_info!(&1.solar_system_id))
|
||||
|
||||
initial_data =
|
||||
initial_data
|
||||
|> Map.put(
|
||||
:wormholes,
|
||||
WandererApp.CachedInfo.get_wormhole_types!()
|
||||
)
|
||||
|> Map.put(
|
||||
:effects,
|
||||
WandererApp.CachedInfo.get_effects!()
|
||||
)
|
||||
|> Map.put(
|
||||
:system_static_infos,
|
||||
system_static_infos |> Enum.map(&map_ui_system_static_info/1)
|
||||
)
|
||||
|> Map.put(:reset, true)
|
||||
|
||||
Process.send_after(
|
||||
self(),
|
||||
{:map_start,
|
||||
%{
|
||||
map_id: map_id,
|
||||
user_characters: user_character_eve_ids,
|
||||
initial_data: initial_data,
|
||||
events: events
|
||||
}},
|
||||
10
|
||||
initial_data =
|
||||
initial_data
|
||||
|> Map.put(
|
||||
:wormholes,
|
||||
WandererApp.CachedInfo.get_wormhole_types!()
|
||||
)
|
||||
|> Map.put(
|
||||
:effects,
|
||||
WandererApp.CachedInfo.get_effects!()
|
||||
)
|
||||
|> Map.put(
|
||||
:system_static_infos,
|
||||
system_static_infos
|
||||
)
|
||||
|> Map.put(:reset, true)
|
||||
|
||||
_ ->
|
||||
Process.send_after(
|
||||
self(),
|
||||
{:map_start,
|
||||
%{
|
||||
map_id: map_id,
|
||||
map_user_settings: map_user_settings,
|
||||
user_characters: user_character_eve_ids,
|
||||
initial_data: initial_data,
|
||||
events: events
|
||||
}},
|
||||
10
|
||||
)
|
||||
else
|
||||
error ->
|
||||
Logger.error(fn -> "map_start_error: #{error}" end)
|
||||
Process.send_after(self(), :no_access, 10)
|
||||
end
|
||||
end
|
||||
|
||||
defp on_map_started(_map_id, _current_user, _user_permissions),
|
||||
do: Process.send_after(self(), :no_access, 10)
|
||||
|
||||
defp _set_autopilot_waypoint(
|
||||
current_user,
|
||||
character_eve_id,
|
||||
@@ -1740,11 +1929,11 @@ defmodule WandererAppWeb.MapLive do
|
||||
end
|
||||
end
|
||||
|
||||
defp _get_system_signatures(system_id),
|
||||
defp get_system_signatures(system_id),
|
||||
do:
|
||||
system_id
|
||||
|> WandererApp.Api.MapSystemSignature.by_system_id!()
|
||||
|> Enum.map(fn %{updated_at: updated_at} = s ->
|
||||
|> Enum.map(fn %{updated_at: updated_at, linked_system_id: linked_system_id} = s ->
|
||||
s
|
||||
|> Map.take([
|
||||
:system_id,
|
||||
@@ -1756,6 +1945,7 @@ defmodule WandererAppWeb.MapLive do
|
||||
:group,
|
||||
:updated_at
|
||||
])
|
||||
|> Map.put(:linked_system, get_system_static_info(linked_system_id))
|
||||
|> Map.put(:updated_at, updated_at |> Calendar.strftime("%Y/%m/%d %H:%M:%S"))
|
||||
end)
|
||||
|
||||
@@ -1821,14 +2011,7 @@ defmodule WandererAppWeb.MapLive do
|
||||
} = _system,
|
||||
_include_static_data? \\ true
|
||||
) do
|
||||
system_static_info =
|
||||
case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do
|
||||
{:ok, system_static_info} ->
|
||||
map_ui_system_static_info(system_static_info)
|
||||
|
||||
_ ->
|
||||
%{}
|
||||
end
|
||||
system_static_info = get_system_static_info(solar_system_id)
|
||||
|
||||
%{
|
||||
id: "#{solar_system_id}",
|
||||
@@ -1844,6 +2027,18 @@ defmodule WandererAppWeb.MapLive do
|
||||
}
|
||||
end
|
||||
|
||||
defp get_system_static_info(nil), do: nil
|
||||
|
||||
defp get_system_static_info(solar_system_id) do
|
||||
case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do
|
||||
{:ok, system_static_info} ->
|
||||
map_ui_system_static_info(system_static_info)
|
||||
|
||||
_ ->
|
||||
%{}
|
||||
end
|
||||
end
|
||||
|
||||
defp map_ui_system_static_info(nil), do: %{}
|
||||
|
||||
defp map_ui_system_static_info(system_static_info),
|
||||
|
||||
@@ -149,3 +149,25 @@
|
||||
</.table>
|
||||
</.async_result>
|
||||
</.modal>
|
||||
|
||||
<.modal
|
||||
:if={assigns |> Map.get(:show_user_settings?, false)}
|
||||
id="map-user-settings-modal"
|
||||
title="Map user settings"
|
||||
show
|
||||
on_cancel={JS.push("hide_user_settings")}
|
||||
>
|
||||
<.form
|
||||
:let={f}
|
||||
:if={assigns |> Map.get(:user_settings_form, false)}
|
||||
for={@user_settings_form}
|
||||
phx-change="update_user_settings"
|
||||
>
|
||||
<.input type="checkbox" field={f[:select_on_spash]} label="Auto select splashed systems" />
|
||||
<.input
|
||||
type="checkbox"
|
||||
field={f[:link_signature_on_splash]}
|
||||
label="Link splashed systems to signatures"
|
||||
/>
|
||||
</.form>
|
||||
</.modal>
|
||||
|
||||
@@ -664,7 +664,7 @@ defmodule WandererAppWeb.MapsLive do
|
||||
%{
|
||||
"layout" => layout
|
||||
} = options_form,
|
||||
%{assigns: %{map_id: map_id, map: map, current_user: current_user}} = socket
|
||||
%{assigns: %{map_id: map_id, map: map}} = socket
|
||||
) do
|
||||
options = %{layout: layout}
|
||||
|
||||
|
||||
2
mix.exs
2
mix.exs
@@ -2,7 +2,7 @@ defmodule WandererApp.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
@source_url "https://github.com/wanderer-industries/wanderer"
|
||||
@version "1.3.6"
|
||||
@version "1.10.0"
|
||||
|
||||
def project do
|
||||
[
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
defmodule WandererApp.Repo.Migrations.AddMapUserSettings do
|
||||
@moduledoc """
|
||||
Updates resources based on their most recent snapshots.
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
create table(:map_user_settings_v1, primary_key: false) do
|
||||
add :id, :uuid, null: false, default: fragment("gen_random_uuid()"), primary_key: true
|
||||
add :settings, :text
|
||||
|
||||
add :map_id,
|
||||
references(:maps_v1,
|
||||
column: :id,
|
||||
name: "map_user_settings_v1_map_id_fkey",
|
||||
type: :uuid,
|
||||
prefix: "public"
|
||||
),
|
||||
primary_key: true,
|
||||
null: false
|
||||
|
||||
add :user_id,
|
||||
references(:user_v1,
|
||||
column: :id,
|
||||
name: "map_user_settings_v1_user_id_fkey",
|
||||
type: :uuid,
|
||||
prefix: "public"
|
||||
),
|
||||
primary_key: true,
|
||||
null: false
|
||||
end
|
||||
|
||||
create unique_index(:map_user_settings_v1, [:map_id, :user_id],
|
||||
name: "map_user_settings_v1_uniq_map_user_index"
|
||||
)
|
||||
end
|
||||
|
||||
def down do
|
||||
drop_if_exists unique_index(:map_user_settings_v1, [:map_id, :user_id],
|
||||
name: "map_user_settings_v1_uniq_map_user_index"
|
||||
)
|
||||
|
||||
drop constraint(:map_user_settings_v1, "map_user_settings_v1_map_id_fkey")
|
||||
|
||||
drop constraint(:map_user_settings_v1, "map_user_settings_v1_user_id_fkey")
|
||||
|
||||
drop table(:map_user_settings_v1)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
defmodule WandererApp.Repo.Migrations.AddSignatureLinkedSystem do
|
||||
@moduledoc """
|
||||
Updates resources based on their most recent snapshots.
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:map_system_signatures_v1) do
|
||||
add :linked_system_id, :bigint
|
||||
end
|
||||
end
|
||||
|
||||
def down do
|
||||
alter table(:map_system_signatures_v1) do
|
||||
remove :linked_system_id
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,167 @@
|
||||
{
|
||||
"attributes": [
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"gen_random_uuid()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "eve_id",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "character_eve_id",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "description",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "linked_system_id",
|
||||
"type": "bigint"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "kind",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "group",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "inserted_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "updated_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": {
|
||||
"deferrable": false,
|
||||
"destination_attribute": "id",
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null,
|
||||
"index?": false,
|
||||
"match_type": null,
|
||||
"match_with": null,
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"name": "map_system_signatures_v1_system_id_fkey",
|
||||
"on_delete": null,
|
||||
"on_update": null,
|
||||
"primary_key?": true,
|
||||
"schema": "public",
|
||||
"table": "map_system_v1"
|
||||
},
|
||||
"size": null,
|
||||
"source": "system_id",
|
||||
"type": "uuid"
|
||||
}
|
||||
],
|
||||
"base_filter": null,
|
||||
"check_constraints": [],
|
||||
"custom_indexes": [],
|
||||
"custom_statements": [],
|
||||
"has_create_action": true,
|
||||
"hash": "B437BC9E9F4607EBD235CBB39B814710E223D532CE09B952C9371257159008F4",
|
||||
"identities": [
|
||||
{
|
||||
"all_tenants?": false,
|
||||
"base_filter": null,
|
||||
"index_name": "map_system_signatures_v1_uniq_system_eve_id_index",
|
||||
"keys": [
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "system_id"
|
||||
},
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "eve_id"
|
||||
}
|
||||
],
|
||||
"name": "uniq_system_eve_id",
|
||||
"nils_distinct?": true,
|
||||
"where": null
|
||||
}
|
||||
],
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"repo": "Elixir.WandererApp.Repo",
|
||||
"schema": null,
|
||||
"table": "map_system_signatures_v1"
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"attributes": [
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"gen_random_uuid()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "settings",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"references": {
|
||||
"deferrable": false,
|
||||
"destination_attribute": "id",
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null,
|
||||
"index?": false,
|
||||
"match_type": null,
|
||||
"match_with": null,
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"name": "map_user_settings_v1_map_id_fkey",
|
||||
"on_delete": null,
|
||||
"on_update": null,
|
||||
"primary_key?": true,
|
||||
"schema": "public",
|
||||
"table": "maps_v1"
|
||||
},
|
||||
"size": null,
|
||||
"source": "map_id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"references": {
|
||||
"deferrable": false,
|
||||
"destination_attribute": "id",
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null,
|
||||
"index?": false,
|
||||
"match_type": null,
|
||||
"match_with": null,
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"name": "map_user_settings_v1_user_id_fkey",
|
||||
"on_delete": null,
|
||||
"on_update": null,
|
||||
"primary_key?": true,
|
||||
"schema": "public",
|
||||
"table": "user_v1"
|
||||
},
|
||||
"size": null,
|
||||
"source": "user_id",
|
||||
"type": "uuid"
|
||||
}
|
||||
],
|
||||
"base_filter": null,
|
||||
"check_constraints": [],
|
||||
"custom_indexes": [],
|
||||
"custom_statements": [],
|
||||
"has_create_action": true,
|
||||
"hash": "88FB044C6F66793E2247BF2CEE17F2E4ED52C007C3DDCE02B6EF583EDDD44D85",
|
||||
"identities": [
|
||||
{
|
||||
"all_tenants?": false,
|
||||
"base_filter": null,
|
||||
"index_name": "map_user_settings_v1_uniq_map_user_index",
|
||||
"keys": [
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "map_id"
|
||||
},
|
||||
{
|
||||
"type": "atom",
|
||||
"value": "user_id"
|
||||
}
|
||||
],
|
||||
"name": "uniq_map_user",
|
||||
"nils_distinct?": true,
|
||||
"where": null
|
||||
}
|
||||
],
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"repo": "Elixir.WandererApp.Repo",
|
||||
"schema": null,
|
||||
"table": "map_user_settings_v1"
|
||||
}
|
||||
Reference in New Issue
Block a user