fix: Updated character tracking

This commit is contained in:
Dmitry Popov
2025-09-03 15:02:53 +02:00
parent d5c18b5de3
commit c433205e89
10 changed files with 297 additions and 263 deletions

View File

@@ -1,7 +1,7 @@
import { useReactFlow } from 'reactflow';
import { useCallback, useRef } from 'react';
import { CommandSelectSystems } from '@/hooks/Mapper/types';
import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
import { CommandSelectSystems } from '@/hooks/Mapper/types';
import { useCallback, useRef } from 'react';
import { useReactFlow } from 'reactflow';
export const useSelectSystems = (onSelectionChange: OnMapSelectionChange) => {
const rf = useReactFlow();

View File

@@ -1,4 +1,3 @@
import { ForwardedRef, useImperativeHandle, useRef } from 'react';
import {
CommandAddConnections,
CommandAddSystems,
@@ -19,8 +18,11 @@ import {
CommandUpdateSystems,
MapHandlers,
} from '@/hooks/Mapper/types/mapHandlers.ts';
import { ForwardedRef, useImperativeHandle, useRef } from 'react';
import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
import {
useCenterSystem,
useCommandsCharacters,
useCommandsConnections,
useMapAddSystems,
@@ -28,10 +30,8 @@ import {
useMapInit,
useMapRemoveSystems,
useMapUpdateSystems,
useCenterSystem,
useSelectSystems,
} from './api';
import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange: OnMapSelectionChange) => {
const mapInit = useMapInit();
@@ -49,9 +49,7 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
const { charactersUpdated, presentCharacters, characterAdded, characterRemoved, characterUpdated } =
useCommandsCharacters();
useImperativeHandle(
ref,
() => {
useImperativeHandle(ref, () => {
return {
command(type, data) {
switch (type) {
@@ -133,7 +131,5 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
}
},
};
},
[],
);
}, []);
};

View File

@@ -1,6 +1,7 @@
export * from './useClipboard';
export * from './useConfirmPopup';
export * from './useEventBuffer';
export * from './useHotkey';
export * from './usePageVisibility';
export * from './useSkipContextMenu';
export * from './useThrottle';
export * from './useConfirmPopup';

View File

@@ -0,0 +1,41 @@
import debounce from 'lodash.debounce';
import { useCallback, useRef } from 'react';
export type UseEventBufferHandler<T> = (event: T) => void;
export const useEventBuffer = <T>(handler: UseEventBufferHandler<T>) => {
// @ts-ignore
const eventsBufferRef = useRef<T[]>([]);
const eventTick = useCallback(
debounce(() => {
if (eventsBufferRef.current.length === 0) {
return;
}
const event = eventsBufferRef.current.shift()!;
handler(event);
// TODO - do not delete THIS code it needs for debug
// console.log('JOipP', `Tick Buff`, eventsBufferRef.current.length);
if (eventsBufferRef.current.length > 0) {
eventTick();
}
}, 10),
[],
);
const eventTickRef = useRef(eventTick);
eventTickRef.current = eventTick;
// @ts-ignore
const handleEvent = useCallback(event => {
if (!eventTickRef.current) {
return;
}
eventsBufferRef.current.push(event);
eventTickRef.current();
}, []);
return { handleEvent };
};

View File

@@ -1,7 +1,7 @@
import { useCallback } from 'react';
import { CommandInit } from '@/hooks/Mapper/types';
import { MapRootData, useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useLoadSystemStatic } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
import { CommandInit } from '@/hooks/Mapper/types';
import { useCallback } from 'react';
export const useMapInit = () => {
const { update } = useMapRootState();

View File

@@ -1,4 +1,3 @@
import { ForwardedRef, useImperativeHandle } from 'react';
import {
CommandAddConnections,
CommandAddSystems,
@@ -8,24 +7,25 @@ import {
CommandCharactersUpdated,
CommandCharacterUpdated,
CommandCommentAdd,
CommandCommentRemoved,
CommandInit,
CommandLinkSignatureToSystem,
CommandMapUpdated,
CommandPingAdded,
CommandPingCancelled,
CommandPresentCharacters,
CommandRemoveConnections,
CommandRemoveSystems,
CommandRoutes,
Commands,
CommandSignaturesUpdated,
CommandTrackingCharactersData,
CommandUpdateConnection,
CommandUpdateSystems,
CommandUserSettingsUpdated,
Commands,
MapHandlers,
CommandCommentRemoved,
CommandPingAdded,
CommandPingCancelled,
} from '@/hooks/Mapper/types/mapHandlers.ts';
import { ForwardedRef, useImperativeHandle } from 'react';
import {
useCommandComments,
@@ -39,9 +39,9 @@ import {
useUserRoutes,
} from './api';
import { useCommandsActivity } from './api/useCommandsActivity';
import { emitMapEvent } from '@/hooks/Mapper/events';
import { DetailedKill } from '../../types/kills';
import { useCommandsActivity } from './api/useCommandsActivity';
export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
const mapInit = useMapInit();
@@ -63,9 +63,7 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
const { pingAdded, pingCancelled } = useCommandPings();
const { characterActivityData, trackingCharactersData, userSettingsUpdated } = useCommandsActivity();
useImperativeHandle(
ref,
() => {
useImperativeHandle(ref, () => {
return {
command(type, data) {
switch (type) {
@@ -183,7 +181,5 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
emitMapEvent({ name: type, data });
},
};
},
[],
);
}, []);
};

View File

@@ -1,7 +1,8 @@
import { useEventBuffer } from '@/hooks/Mapper/hooks';
import usePageVisibility from '@/hooks/Mapper/hooks/usePageVisibility.ts';
import { MapHandlers } from '@/hooks/Mapper/types/mapHandlers.ts';
import { RefObject, useCallback, useEffect, useRef } from 'react';
import debounce from 'lodash.debounce';
import usePageVisibility from '@/hooks/Mapper/hooks/usePageVisibility.ts';
// const inIndex = 0;
// const prevEventTime = +new Date();
@@ -10,10 +11,28 @@ const LAST_VERSION_KEY = 'wandererLastVersion';
// @ts-ignore
export const useMapperHandlers = (handlerRefs: RefObject<MapHandlers>[], hooksRef: RefObject<any>) => {
const visible = usePageVisibility();
const wasHiddenOnce = useRef(false);
const visibleRef = useRef(visible);
visibleRef.current = visible;
// @ts-ignore
const handleBufferedEvent = useCallback(({ type, body }) => {
if (!visibleRef.current) {
return;
}
handlerRefs.forEach(ref => {
if (!ref.current) {
return;
}
ref.current?.command(type, body);
});
}, []);
const { handleEvent: handleMapEvent } = useEventBuffer<any>(handleBufferedEvent);
// TODO - do not delete THIS code it needs for debug
// const [record, setRecord] = useLocalStorageState<boolean>('record', {
// defaultValue: false,
@@ -54,52 +73,6 @@ export const useMapperHandlers = (handlerRefs: RefObject<MapHandlers>[], hooksRe
[hooksRef.current],
);
// @ts-ignore
const eventsBufferRef = useRef<{ type; body }[]>([]);
const eventTick = useCallback(
debounce(() => {
if (eventsBufferRef.current.length === 0) {
return;
}
const { type, body } = eventsBufferRef.current.shift()!;
handlerRefs.forEach(ref => {
if (!ref.current) {
return;
}
ref.current?.command(type, body);
});
// TODO - do not delete THIS code it needs for debug
// console.log('JOipP', `Tick Buff`, eventsBufferRef.current.length);
if (eventsBufferRef.current.length > 0) {
eventTick();
}
}, 10),
[],
);
const eventTickRef = useRef(eventTick);
eventTickRef.current = eventTick;
// @ts-ignore
const handleMapEvent = useCallback(({ type, body }) => {
// TODO - do not delete THIS code it needs for debug
// const currentTime = +new Date();
// const timeDiff = currentTime - prevEventTime;
// prevEventTime = currentTime;
// console.log('JOipP', `IN [${inIndex++}] [${timeDiff}] ${getFormattedTime()}`, { type, body });
if (!eventTickRef.current || !visibleRef.current) {
return;
}
eventsBufferRef.current.push({ type, body });
eventTickRef.current();
}, []);
useEffect(() => {
if (!visible && !wasHiddenOnce.current) {
wasHiddenOnce.current = true;

View File

@@ -216,8 +216,7 @@ defmodule WandererApp.Map.Server.CharactersImpl do
{:ok, presence_character_ids} =
WandererApp.Cache.lookup("map_#{map_id}:presence_character_ids", [])
WandererApp.Cache.lookup!("maps:#{map_id}:tracked_characters", [])
|> Enum.filter(fn character_id -> character_id in presence_character_ids end)
presence_character_ids
|> Enum.map(fn character_id ->
Task.start_link(fn ->
character_updates =

View File

@@ -703,6 +703,18 @@ defmodule WandererAppWeb.MapCoreEventHandler do
Process.send_after(self(), %{event: :load_map_pings}, 200)
Process.send_after(
self(),
%{
event: :maybe_select_system,
payload: %{
character_id: main_character_id,
solar_system_id: nil
}
},
200
)
if needs_tracking_setup do
Process.send_after(self(), %{event: :show_tracking}, 10)

View File

@@ -44,16 +44,24 @@ defmodule WandererAppWeb.MapSystemsEventHandler do
current_user: current_user,
tracked_characters: tracked_characters,
map_id: map_id,
map_user_settings: map_user_settings
map_user_settings: map_user_settings,
main_character_eve_id: main_character_eve_id,
following_character_eve_id: following_character_eve_id
}
} = socket
) do
character =
if is_nil(character_id) do
tracked_characters
|> Enum.find(fn tracked_character ->
tracked_character.eve_id == (following_character_eve_id || main_character_eve_id)
end)
else
tracked_characters
|> Enum.find(fn tracked_character -> tracked_character.id == character_id end)
end
is_user_character =
not is_nil(character)
is_user_character = not is_nil(character)
is_select_on_spash =
map_user_settings
@@ -61,10 +69,9 @@ defmodule WandererAppWeb.MapSystemsEventHandler do
|> WandererApp.MapUserSettingsRepo.get_boolean_setting("select_on_spash")
is_following =
case WandererApp.MapUserSettingsRepo.get(map_id, current_user.id) do
{:ok, %{following_character_eve_id: following_character_eve_id}}
when not is_nil(following_character_eve_id) ->
is_user_character && following_character_eve_id == character.eve_id
case is_user_character && not is_nil(following_character_eve_id) do
true ->
following_character_eve_id == character.eve_id
_ ->
false
@@ -77,8 +84,17 @@ defmodule WandererAppWeb.MapSystemsEventHandler do
else
# Always select the system when auto-select is enabled (following or select_on_spash).
# The frontend will handle deselecting other systems
#
select_solar_system_id =
if not is_nil(solar_system_id) do
"#{solar_system_id}"
else
{:ok, character} = WandererApp.Character.get_map_character(map_id, character.id)
"#{character.solar_system_id}"
end
socket
|> MapEventHandler.push_map_event("select_system", solar_system_id)
|> MapEventHandler.push_map_event("select_system", select_solar_system_id)
end
end