mirror of
https://github.com/wanderer-industries/wanderer
synced 2026-02-19 04:16:29 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f3387e4ff | ||
|
|
95d2fa232a | ||
|
|
eed1d8bc27 | ||
|
|
c451735559 | ||
|
|
aa586b7994 | ||
|
|
39317831f9 | ||
|
|
b71bc94d4f | ||
|
|
0e920a58e6 | ||
|
|
9385751332 | ||
|
|
ffaa48ff9e | ||
|
|
94665f4e68 | ||
|
|
e9fd0665c8 | ||
|
|
9a0271f711 | ||
|
|
0c68535656 | ||
|
|
9ed350befa | ||
|
|
c410f5f37d | ||
|
|
8559be00f0 | ||
|
|
1a24ee4c74 | ||
|
|
de86703737 | ||
|
|
c5af43dca1 | ||
|
|
549fa1d2cf |
88
CHANGELOG.md
88
CHANGELOG.md
@@ -2,6 +2,94 @@
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.96.4](https://github.com/wanderer-industries/wanderer/compare/v1.96.3...v1.96.4) (2026-02-17)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Change character token validity status. Now we will see red frame and icon for tracked characters which token was expired.
|
||||
|
||||
## [v1.96.3](https://github.com/wanderer-industries/wanderer/compare/v1.96.2...v1.96.3) (2026-02-15)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* tracking: Fixed character tracking issues
|
||||
|
||||
## [v1.96.2](https://github.com/wanderer-industries/wanderer/compare/v1.96.1...v1.96.2) (2026-02-13)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Added icons for RoutesBy
|
||||
|
||||
## [v1.96.1](https://github.com/wanderer-industries/wanderer/compare/v1.96.0...v1.96.1) (2026-02-12)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.96.0](https://github.com/wanderer-industries/wanderer/compare/v1.95.0...v1.96.0) (2026-02-12)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* signatures: Fixed creator visibility issues. Added 4.5 hour color for unsplashed
|
||||
|
||||
## [v1.95.0](https://github.com/wanderer-industries/wanderer/compare/v1.94.0...v1.95.0) (2026-02-11)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* subscriptions: Added top map donators support
|
||||
|
||||
* Added lost files
|
||||
|
||||
* Added paywall for RoutesBy widget
|
||||
|
||||
* removed unnecessary env variable for routes
|
||||
|
||||
* Add systems with Security Status cleaning. Add trade hubs. Add ability to store data for this widget
|
||||
|
||||
* Add Routes By widget. Allow to find nearest blue loot and red loot stations. Added ability to set waypoint to station.
|
||||
|
||||
* auto add system on sig addition
|
||||
|
||||
* map: Reviewed changes
|
||||
|
||||
* map: Logic for multiple owner updates
|
||||
|
||||
* map: wip New Dialog for Structure Owners
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* signatures: Fixed back linked sigs data sync and leading to system override issues
|
||||
|
||||
* signatures: Moved C1/C2/C3 and C4/C5 to the bottom of the available list
|
||||
|
||||
* use cache for sse
|
||||
|
||||
* adding system when linked signature is provided
|
||||
|
||||
* saving updates to unknown sigs
|
||||
|
||||
* wh position and sig type change
|
||||
|
||||
* api updates and linked sig addition
|
||||
|
||||
* api fixes and format
|
||||
|
||||
* Wrong file added to commits
|
||||
|
||||
## [v1.94.0](https://github.com/wanderer-industries/wanderer/compare/v1.93.0...v1.94.0) (2026-02-08)
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import { emitMapEvent } from '@/hooks/Mapper/events';
|
||||
import { isDocked } from '@/hooks/Mapper/helpers/isDocked.ts';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { CharacterTypeRaw } from '@/hooks/Mapper/types';
|
||||
import { Commands, OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
|
||||
import { useAutoAnimate } from '@formkit/auto-animate/react';
|
||||
import clsx from 'clsx';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import { useCallback } from 'react';
|
||||
import classes from './Characters.module.scss';
|
||||
import {
|
||||
TooltipPosition,
|
||||
WdEveEntityPortrait,
|
||||
WdEveEntityPortraitSize,
|
||||
WdTooltipWrapper,
|
||||
} from '@/hooks/Mapper/components/ui-kit';
|
||||
import { WdCharStateWrapper } from '@/hooks/Mapper/components/characters/components/WdCharStateWrapper.tsx';
|
||||
|
||||
interface CharactersProps {
|
||||
data: CharacterTypeRaw[];
|
||||
}
|
||||
@@ -17,7 +22,7 @@ export const Characters = ({ data }: CharactersProps) => {
|
||||
|
||||
const {
|
||||
outCommand,
|
||||
data: { mainCharacterEveId, followingCharacterEveId },
|
||||
data: { mainCharacterEveId, followingCharacterEveId, expiredCharacters },
|
||||
} = useMapRootState();
|
||||
|
||||
const handleSelect = useCallback(async (character: CharacterTypeRaw) => {
|
||||
@@ -35,61 +40,48 @@ export const Characters = ({ data }: CharactersProps) => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const items = data.map(character => (
|
||||
<li
|
||||
key={character.eve_id}
|
||||
className="flex flex-col items-center justify-center"
|
||||
onClick={() => handleSelect(character)}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
'overflow-hidden relative',
|
||||
'flex w-[35px] h-[35px] rounded-[4px] border-[1px] border-solid bg-transparent cursor-pointer',
|
||||
'transition-colors duration-250 hover:bg-stone-300/90',
|
||||
{
|
||||
['border-stone-800/90']: !character.online,
|
||||
['border-lime-600/70']: character.online,
|
||||
},
|
||||
)}
|
||||
title={character.name}
|
||||
>
|
||||
{mainCharacterEveId === character.eve_id && (
|
||||
<span
|
||||
className={clsx(
|
||||
'absolute top-[2px] left-[22px] w-[9px] h-[9px]',
|
||||
'text-yellow-500 text-[9px] rounded-[1px] z-10',
|
||||
'pi',
|
||||
PrimeIcons.STAR_FILL,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
const items = data.map(character => {
|
||||
const isExpired = expiredCharacters.includes(character.eve_id);
|
||||
|
||||
{followingCharacterEveId === character.eve_id && (
|
||||
<span
|
||||
className={clsx(
|
||||
'absolute top-[23px] left-[22px] w-[10px] h-[10px]',
|
||||
'text-sky-300 text-[10px] rounded-[1px] z-10',
|
||||
'pi pi-angle-double-right',
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{isDocked(character.location) && <div className={classes.Docked} />}
|
||||
<div
|
||||
className={clsx(
|
||||
'flex w-full h-full bg-transparent cursor-pointer',
|
||||
'bg-center bg-no-repeat bg-[length:100%]',
|
||||
'transition-opacity',
|
||||
'shadow-[inset_0_1px_6px_1px_#000000]',
|
||||
{
|
||||
['opacity-60']: !character.online,
|
||||
['opacity-100']: character.online,
|
||||
},
|
||||
)}
|
||||
style={{ backgroundImage: `url(https://images.evetech.net/characters/${character.eve_id}/portrait)` }}
|
||||
></div>
|
||||
</div>
|
||||
</li>
|
||||
));
|
||||
return (
|
||||
<li
|
||||
key={character.eve_id}
|
||||
className="flex flex-col items-center justify-center"
|
||||
onClick={() => handleSelect(character)}
|
||||
>
|
||||
<WdTooltipWrapper
|
||||
position={TooltipPosition.bottom}
|
||||
content={isExpired ? `Token is expired for ${character.name}` : character.name}
|
||||
>
|
||||
<WdCharStateWrapper
|
||||
eve_id={character.eve_id}
|
||||
location={character.location}
|
||||
isExpired={isExpired}
|
||||
isMain={mainCharacterEveId === character.eve_id}
|
||||
isFollowing={followingCharacterEveId === character.eve_id}
|
||||
isOnline={character.online}
|
||||
>
|
||||
<WdEveEntityPortrait
|
||||
eveId={character.eve_id}
|
||||
size={WdEveEntityPortraitSize.w33}
|
||||
className={clsx(
|
||||
'flex w-full h-full bg-transparent cursor-pointer',
|
||||
'bg-center bg-no-repeat bg-[length:100%]',
|
||||
'transition-opacity',
|
||||
'shadow-[inset_0_1px_6px_1px_#000000]',
|
||||
{
|
||||
['opacity-60']: !isExpired && !character.online,
|
||||
['opacity-100']: !isExpired && character.online,
|
||||
['opacity-50']: isExpired,
|
||||
},
|
||||
'!border-0',
|
||||
)}
|
||||
/>
|
||||
</WdCharStateWrapper>
|
||||
</WdTooltipWrapper>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<ul className="flex gap-1 characters" id="characters" ref={parent}>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import clsx from 'clsx';
|
||||
import { PrimeIcons } from 'primereact/api';
|
||||
import { isDocked } from '@/hooks/Mapper/helpers/isDocked.ts';
|
||||
import classes from './WdCharStateWrapper.module.scss';
|
||||
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
|
||||
import { LocationRaw } from '@/hooks/Mapper/types';
|
||||
|
||||
type WdCharStateWrapperProps = {
|
||||
eve_id: string;
|
||||
isExpired?: boolean;
|
||||
isMain?: boolean;
|
||||
isFollowing?: boolean;
|
||||
location: LocationRaw | null;
|
||||
isOnline: boolean;
|
||||
} & WithChildren;
|
||||
|
||||
export const WdCharStateWrapper = ({
|
||||
location,
|
||||
isOnline,
|
||||
isMain,
|
||||
isFollowing,
|
||||
isExpired,
|
||||
children,
|
||||
}: WdCharStateWrapperProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'overflow-hidden relative',
|
||||
'flex w-[35px] h-[35px] rounded-[4px] border-[1px] border-solid bg-transparent cursor-pointer',
|
||||
'transition-colors duration-250 hover:bg-stone-300/90',
|
||||
{
|
||||
['border-stone-800/90']: !isExpired && !isOnline,
|
||||
['border-lime-600/70']: !isExpired && isOnline,
|
||||
['border-red-600/70']: isExpired,
|
||||
},
|
||||
)}
|
||||
>
|
||||
{isMain && (
|
||||
<span
|
||||
className={clsx(
|
||||
'absolute top-[2px] left-[22px] w-[9px] h-[9px]',
|
||||
'text-yellow-500 text-[9px] rounded-[1px] z-10',
|
||||
'pi',
|
||||
PrimeIcons.STAR_FILL,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{isFollowing && (
|
||||
<span
|
||||
className={clsx(
|
||||
'absolute top-[23px] left-[22px] w-[10px] h-[10px]',
|
||||
'text-sky-300 text-[10px] rounded-[1px] z-10',
|
||||
'pi pi-angle-double-right',
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{isDocked(location) && <div className={classes.Docked} />}
|
||||
{isExpired && (
|
||||
<span
|
||||
className={clsx(
|
||||
'absolute top-[4px] left-[4px] w-[10px] h-[10px]',
|
||||
'text-red-400 text-[10px] rounded-[1px] z-10',
|
||||
'pi pi-exclamation-triangle',
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './WdCharStateWrapper.tsx';
|
||||
@@ -4,12 +4,16 @@ import { DataTable } from 'primereact/datatable';
|
||||
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';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
|
||||
export const TrackingCharactersList = () => {
|
||||
const [selected, setSelected] = useState<TrackingCharacter[]>([]);
|
||||
const { trackingCharacters, main, following, updateTracking } = useTracking();
|
||||
const refVars = useRef({ trackingCharacters });
|
||||
refVars.current = { trackingCharacters };
|
||||
const {
|
||||
data: { expiredCharacters },
|
||||
} = useMapRootState();
|
||||
|
||||
useEffect(() => {
|
||||
setSelected(trackingCharacters.filter(x => x.tracked));
|
||||
@@ -66,7 +70,9 @@ export const TrackingCharactersList = () => {
|
||||
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
headerClassName="[&_div]:ml-2"
|
||||
body={row => {
|
||||
return <CharacterCard showCorporationLogo showTicker isOwn {...row.character} />;
|
||||
const isExpired = expiredCharacters.includes(row.character.eve_id);
|
||||
|
||||
return <CharacterCard showCorporationLogo showTicker isOwn isExpired={isExpired} {...row.character} />;
|
||||
}}
|
||||
/>
|
||||
</DataTable>
|
||||
|
||||
@@ -38,7 +38,7 @@ const TrackingDialogComp = ({ visible, onHide }: TrackingDialogProps) => {
|
||||
resizable={false}
|
||||
visible={visible}
|
||||
onHide={onHide}
|
||||
className="w-[640px] h-[400px] text-text-color min-h-0"
|
||||
className="w-[640px] h-[600px] text-text-color min-h-0"
|
||||
>
|
||||
<TabView
|
||||
className="vertical-tabs-container h-full [&_.p-tabview-panels]:!pr-0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createContext, useCallback, useContext, useRef, useState, useEffect } from 'react';
|
||||
import { createContext, useCallback, useContext, useRef, useState } from 'react';
|
||||
import { Commands, OutCommand, TrackingCharacter } from '@/hooks/Mapper/types';
|
||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||
import { IncomingEvent, WithChildren } from '@/hooks/Mapper/types/common.ts';
|
||||
|
||||
@@ -17,6 +17,7 @@ import { useCallback } from 'react';
|
||||
import classes from './CharacterCard.module.scss';
|
||||
import { ZKB_ICON } from '@/hooks/Mapper/icons';
|
||||
import { charEveWhoLink, charZKBLink } from '@/hooks/Mapper/helpers/linkHelpers.ts';
|
||||
import { WdCharStateWrapper } from '../../characters/components';
|
||||
|
||||
export type CharacterCardProps = {
|
||||
compact?: boolean;
|
||||
@@ -29,6 +30,9 @@ export type CharacterCardProps = {
|
||||
showAllyLogo?: boolean;
|
||||
showAllyLogoPlaceholder?: boolean;
|
||||
simpleMode?: boolean;
|
||||
isExpired?: boolean;
|
||||
isMain?: boolean;
|
||||
isFollowing?: boolean;
|
||||
} & WithIsOwnCharacter &
|
||||
WithClassName;
|
||||
|
||||
@@ -55,6 +59,10 @@ export const CharacterCard = ({
|
||||
showTicker,
|
||||
useSystemsCache,
|
||||
className,
|
||||
isExpired,
|
||||
isMain,
|
||||
isFollowing,
|
||||
|
||||
...char
|
||||
}: CharacterCardInnerProps) => {
|
||||
const handleSelect = useCallback(() => {
|
||||
@@ -204,7 +212,22 @@ export const CharacterCard = ({
|
||||
<div className={clsx('w-full text-xs box-border')} onClick={handleSelect}>
|
||||
<div className="w-full flex items-center gap-2">
|
||||
<div className="flex items-center gap-1">
|
||||
<WdEveEntityPortrait eveId={char.eve_id} size={WdEveEntityPortraitSize.w33} />
|
||||
<WdCharStateWrapper
|
||||
eve_id={char.eve_id}
|
||||
location={char.location}
|
||||
isExpired={isExpired}
|
||||
isOnline={char.online}
|
||||
isMain={isMain}
|
||||
isFollowing={isFollowing}
|
||||
>
|
||||
<WdEveEntityPortrait
|
||||
eveId={char.eve_id}
|
||||
size={WdEveEntityPortraitSize.w33}
|
||||
className={clsx({
|
||||
['border-red-600/50']: isExpired,
|
||||
})}
|
||||
/>
|
||||
</WdCharStateWrapper>
|
||||
|
||||
{showCorporationLogo && (
|
||||
<WdTooltipWrapper position={TooltipPosition.top} content={char.corporation_name}>
|
||||
|
||||
@@ -56,6 +56,7 @@ export type MapRootData = MapUnionTypes & {
|
||||
trackingCharactersData: TrackingCharacter[];
|
||||
loadingPublicRoutes: boolean;
|
||||
map_slug: string | null;
|
||||
expiredCharacters: string[];
|
||||
};
|
||||
|
||||
const INITIAL_DATA: MapRootData = {
|
||||
@@ -102,6 +103,7 @@ const INITIAL_DATA: MapRootData = {
|
||||
pings: [],
|
||||
loadingPublicRoutes: false,
|
||||
map_slug: null,
|
||||
expiredCharacters: [],
|
||||
};
|
||||
|
||||
export enum InterfaceStoredSettingsProps {
|
||||
|
||||
@@ -29,6 +29,7 @@ export const useMapInit = () => {
|
||||
following_character_eve_id,
|
||||
user_hubs,
|
||||
map_slug,
|
||||
expired_characters,
|
||||
} = props;
|
||||
|
||||
const updateData: Partial<MapRootData> = {};
|
||||
@@ -108,6 +109,10 @@ export const useMapInit = () => {
|
||||
updateData.map_slug = map_slug;
|
||||
}
|
||||
|
||||
if ('expired_characters' in props) {
|
||||
updateData.expiredCharacters = expired_characters;
|
||||
}
|
||||
|
||||
update(updateData);
|
||||
},
|
||||
[update, addSystemStatic],
|
||||
|
||||
@@ -108,6 +108,7 @@ export type CommandInit = {
|
||||
main_character_eve_id?: string | null;
|
||||
following_character_eve_id?: string | null;
|
||||
map_slug?: string;
|
||||
expired_characters: string[];
|
||||
};
|
||||
|
||||
export type CommandAddSystems = SolarSystemRawType[];
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 285 KiB |
@@ -854,16 +854,11 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
|
||||
with {:ok, _} <- WandererApp.Api.Character.update(character, attrs) do
|
||||
WandererApp.Character.update_character(character_id, attrs)
|
||||
:ok
|
||||
else
|
||||
error ->
|
||||
Logger.error("Failed to clear tokens for #{character_id}: #{inspect(error)}")
|
||||
end
|
||||
|
||||
Phoenix.PubSub.broadcast(
|
||||
WandererApp.PubSub,
|
||||
"character:#{character_id}",
|
||||
:character_token_invalid
|
||||
)
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
@@ -314,10 +314,10 @@ defmodule WandererApp.Map.Server.CharactersImpl do
|
||||
settings
|
||||
|> Enum.each(fn s ->
|
||||
Logger.info(fn ->
|
||||
"[CharacterCleanup] Map #{map_id} - destroying settings and removing character #{s.character_id}"
|
||||
"[CharacterCleanup] Map #{map_id} - untracking settings and removing character #{s.character_id}"
|
||||
end)
|
||||
|
||||
WandererApp.MapCharacterSettingsRepo.destroy!(s)
|
||||
WandererApp.MapCharacterSettingsRepo.untrack!(%{map_id: s.map_id, character_id: s.character_id})
|
||||
remove_character(map_id, s.character_id)
|
||||
end)
|
||||
|
||||
@@ -780,10 +780,14 @@ defmodule WandererApp.Map.Server.CharactersImpl do
|
||||
old_alliance_id = Map.get(cached_values, alliance_key)
|
||||
|
||||
if character.alliance_id != old_alliance_id do
|
||||
{
|
||||
[{:character_alliance, %{alliance_id: character.alliance_id}} | updates],
|
||||
Map.put(cache_updates, alliance_key, character.alliance_id)
|
||||
}
|
||||
cache_updates = Map.put(cache_updates, alliance_key, character.alliance_id)
|
||||
|
||||
if is_nil(old_alliance_id) do
|
||||
# Initial cache population, not a real change - just update cache
|
||||
{updates, cache_updates}
|
||||
else
|
||||
{[{:character_alliance, %{alliance_id: character.alliance_id}} | updates], cache_updates}
|
||||
end
|
||||
else
|
||||
{updates, cache_updates}
|
||||
end
|
||||
@@ -802,10 +806,15 @@ defmodule WandererApp.Map.Server.CharactersImpl do
|
||||
old_corporation_id = Map.get(cached_values, corporation_key)
|
||||
|
||||
if character.corporation_id != old_corporation_id do
|
||||
{
|
||||
[{:character_corporation, %{corporation_id: character.corporation_id}} | updates],
|
||||
Map.put(cache_updates, corporation_key, character.corporation_id)
|
||||
}
|
||||
cache_updates = Map.put(cache_updates, corporation_key, character.corporation_id)
|
||||
|
||||
if is_nil(old_corporation_id) do
|
||||
# Initial cache population, not a real change - just update cache
|
||||
{updates, cache_updates}
|
||||
else
|
||||
{[{:character_corporation, %{corporation_id: character.corporation_id}} | updates],
|
||||
cache_updates}
|
||||
end
|
||||
else
|
||||
{updates, cache_updates}
|
||||
end
|
||||
@@ -952,12 +961,28 @@ defmodule WandererApp.Map.Server.CharactersImpl do
|
||||
{:ok, character} =
|
||||
WandererApp.Character.get_character(character_id)
|
||||
|
||||
add_character(map_id, character, true)
|
||||
case WandererApp.Api.MapCharacterSettings.read_by_map_and_character(%{
|
||||
map_id: map_id,
|
||||
character_id: character_id
|
||||
}) do
|
||||
{:ok, %{tracked: false}} ->
|
||||
# Was explicitly untracked (e.g., by permission cleanup) - don't re-enable
|
||||
Logger.debug(fn ->
|
||||
"[CharactersImpl] Skipping re-track for character #{character_id} on map #{map_id} - " <>
|
||||
"character was explicitly untracked"
|
||||
end)
|
||||
|
||||
WandererApp.Character.TrackerManager.update_track_settings(character_id, %{
|
||||
map_id: map_id,
|
||||
track: true
|
||||
})
|
||||
add_character(map_id, character, false)
|
||||
|
||||
_ ->
|
||||
# New character or already tracked - enable tracking
|
||||
add_character(map_id, character, true)
|
||||
|
||||
WandererApp.Character.TrackerManager.update_track_settings(character_id, %{
|
||||
map_id: map_id,
|
||||
track: true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
# Broadcasts permission update to trigger LiveView refresh for the character's user.
|
||||
|
||||
@@ -385,14 +385,6 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
|
||||
end
|
||||
end
|
||||
|
||||
defp handle_tracking_event(:invalid_token_message, socket, _map_id) do
|
||||
socket
|
||||
|> put_flash(
|
||||
:error,
|
||||
"One of your characters has expired token. Please refresh it on characters page."
|
||||
)
|
||||
end
|
||||
|
||||
defp handle_tracking_event(:map_character_limit, socket, _map_id) do
|
||||
socket
|
||||
|> put_flash(
|
||||
|
||||
@@ -553,23 +553,14 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
{:ok, map_character_ids} <-
|
||||
WandererApp.Cache.lookup("map_#{map_id}:presence_character_ids", []) do
|
||||
events =
|
||||
case tracked_characters |> Enum.any?(&(&1.access_token == nil)) do
|
||||
case track_character && not has_tracked_characters? do
|
||||
true ->
|
||||
[:invalid_token_message]
|
||||
[:empty_tracked_characters]
|
||||
|
||||
_ ->
|
||||
[]
|
||||
end
|
||||
|
||||
events =
|
||||
case track_character && not has_tracked_characters? do
|
||||
true ->
|
||||
events ++ [:empty_tracked_characters]
|
||||
|
||||
_ ->
|
||||
events
|
||||
end
|
||||
|
||||
character_limit_reached? = map_character_ids |> Enum.count() >= characters_limit
|
||||
|
||||
events =
|
||||
@@ -623,6 +614,8 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
nil
|
||||
end
|
||||
|
||||
expired_characters = tracked_characters |> Enum.filter(&(&1.access_token == nil)) |> Enum.map(& &1.eve_id)
|
||||
|
||||
initial_data =
|
||||
%{
|
||||
kills: kills_data,
|
||||
@@ -630,6 +623,7 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
map_character_ids
|
||||
|> WandererApp.Character.get_character_eve_ids!(),
|
||||
user_characters: tracked_characters |> Enum.map(& &1.eve_id),
|
||||
expired_characters: expired_characters,
|
||||
system_static_infos: nil,
|
||||
wormholes: nil,
|
||||
effects: nil,
|
||||
|
||||
@@ -55,16 +55,6 @@ defmodule WandererAppWeb.MapLive do
|
||||
{:noreply, socket |> push_navigate(to: ~p"/#{map_slug}")}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:character_token_invalid, socket),
|
||||
do:
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(
|
||||
:error,
|
||||
"One of your characters has expired token. Please refresh it on characters page."
|
||||
)}
|
||||
|
||||
def handle_info(:no_main_character_set, socket),
|
||||
do:
|
||||
{:noreply,
|
||||
|
||||
2
mix.exs
2
mix.exs
@@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do
|
||||
|
||||
@source_url "https://github.com/wanderer-industries/wanderer"
|
||||
|
||||
@version "1.94.0"
|
||||
@version "1.96.4"
|
||||
|
||||
def project do
|
||||
[
|
||||
|
||||
53
priv/posts/2026/02-12-eve-creator-awards.md
Normal file
53
priv/posts/2026/02-12-eve-creator-awards.md
Normal file
@@ -0,0 +1,53 @@
|
||||
%{
|
||||
title: "EVE Creator Awards - Nominate Wanderer!",
|
||||
author: "Wanderer Team",
|
||||
cover_image_uri: "/images/news/2026/02-12-eve-creator-awards/cover.jpg",
|
||||
tags: ~w(event community awards nomination),
|
||||
description: "CCP has opened nominations for the EVE Creator Awards! Support Wanderer by voting for Third-Party App of the Year and Developer of the Year."
|
||||
}
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
### EVE Creator Awards - We Need Your Vote!
|
||||
|
||||
CCP has opened nominations for the **EVE Creator Awards**, including **Best Third-Party App** and **Developer of the Year**, and you can support us by voting.
|
||||
|
||||
---
|
||||
|
||||
### How to Nominate Us
|
||||
|
||||
You can nominate us for **Third-Party App of the Year**, and choose one of the team as **Developer of the Year**: Dan Sylvest, vvrong, or Gustav Oswaldo.
|
||||
|
||||
**App field** may be filled with: `Wanderer` / `https://wanderer.ltd/`
|
||||
|
||||
---
|
||||
|
||||
### A Bit of Stats
|
||||
|
||||
Over the past months, Wanderer has grown to more than **7,000 monthly users**, with pilots joining from all around the world.
|
||||
|
||||
---
|
||||
|
||||
### Meet the Team
|
||||
|
||||
- **Dan Sylvest** — leads frontend, design, and frontend architecture, along with several supporting services.
|
||||
- **vvrong** (you know him as Demiro) — responsible for backend development, core architecture, and APIs, with additional frontend contributions.
|
||||
- **Gustav Oswaldo** — contributes across backend and frontend, including zKillboard-related services, APIs, and bots.
|
||||
|
||||
---
|
||||
|
||||
### Vote Now
|
||||
|
||||
- **[Vote for us here](https://eve-creator-awards.paperform.co/)**
|
||||
- **[Read the announcement](https://www.eveonline.com/news/view/eve-creator-awards)**
|
||||
|
||||
---
|
||||
|
||||
Thank you for your support!
|
||||
|
||||
Fly safe,
|
||||
**Wanderer Team**
|
||||
|
||||
---
|
||||
BIN
priv/static/images/30747_64.png
Normal file
BIN
priv/static/images/30747_64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
BIN
priv/static/images/89219_64.png
Normal file
BIN
priv/static/images/89219_64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
BIN
priv/static/images/concord-so.png
Normal file
BIN
priv/static/images/concord-so.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
priv/static/images/map.png
Normal file
BIN
priv/static/images/map.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
priv/static/images/market.png
Normal file
BIN
priv/static/images/market.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Reference in New Issue
Block a user