Compare commits

...

270 Commits

Author SHA1 Message Date
CI
681ba21d39 chore: release version v1.67.4 2025-06-08 18:56:40 +00:00
Dmitry Popov
aef62189ee Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-08 20:56:07 +02:00
Dmitry Popov
09f70ac817 fix(Core): Fixed issue with system splash updates 2025-06-08 20:55:57 +02:00
CI
1eacb22143 chore: release version v1.67.3 2025-06-08 18:55:40 +00:00
Dmitry Popov
8524bad377 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-08 20:55:10 +02:00
Dmitry Popov
9d899243d1 fix(Core): Fixed issue with system splash updates 2025-06-08 20:54:59 +02:00
CI
9acf20a639 chore: release version v1.67.2 2025-06-08 16:57:01 +00:00
Dmitry Popov
71ef6b2e82 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-08 18:56:35 +02:00
Dmitry Popov
5e34d95dd2 chore: release version v1.66.25 2025-06-08 18:56:32 +02:00
CI
25a809c064 chore: release version v1.67.1 2025-06-08 16:46:28 +00:00
Dmitry Popov
f760498150 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-08 18:45:56 +02:00
Dmitry Popov
328301a375 chore: release version v1.66.25 2025-06-08 18:45:53 +02:00
CI
f28e7ebbbb chore: release version v1.67.0
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-08 14:27:48 +00:00
Dmitry Popov
bfa84af71e Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-08 16:24:32 +02:00
Dmitry Popov
42cd1ba976 feat(Core): Added support for WANDERER_CHARACTER_TRACKING_PAUSE_DISABLED env variable to pause inactive character trackers 2025-06-08 16:24:29 +02:00
CI
88cba866fd chore: release version v1.66.25 2025-06-08 11:33:36 +00:00
Dmitry Popov
af2876a84b Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-08 13:33:09 +02:00
Dmitry Popov
c5b15bfa78 fix(Core): Disabled kills fetching based on env settings 2025-06-08 13:33:05 +02:00
CI
85f00a63c2 chore: release version v1.66.24 2025-06-08 09:27:32 +00:00
Dmitry Popov
05f427bcd7 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-08 11:26:53 +02:00
Dmitry Popov
69f4c41534 chore: release version v1.66.15 2025-06-08 11:26:50 +02:00
CI
30b9239a8b chore: release version v1.66.23 2025-06-08 09:15:07 +00:00
Dmitry Popov
2061a83c59 chore: release version v1.66.15 2025-06-08 11:14:30 +02:00
Dmitry Popov
24e723de07 Merge branch 'tracking-controls' 2025-06-08 11:10:22 +02:00
Dmitry Popov
27b5694885 chore: release version v1.66.15 2025-06-08 11:03:13 +02:00
Dmitry Popov
4093f28cee chore: release version v1.66.15 2025-06-08 10:45:41 +02:00
Dmitry Popov
08aaf2f2dd chore: release version v1.66.15 2025-06-08 10:19:25 +02:00
CI
5a927e5ba5 chore: release version v1.66.22
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-07 16:11:48 +00:00
Dmitry Popov
10fafcf59f Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 18:11:17 +02:00
Dmitry Popov
be87591801 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 18:11:14 +02:00
CI
086d4378d3 chore: release version v1.66.21 2025-06-07 16:03:22 +00:00
Dmitry Popov
e982275905 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 18:02:37 +02:00
Dmitry Popov
77c02703e9 fix(Core): Fixed kills fetching based on env settings 2025-06-07 18:02:34 +02:00
CI
0ef27d4f95 chore: release version v1.66.20
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-07 15:41:18 +00:00
Dmitry Popov
5edc27744e Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 17:40:52 +02:00
Dmitry Popov
02ff887fee Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 17:40:48 +02:00
CI
3a30eeb59f chore: release version v1.66.19 2025-06-07 15:31:53 +00:00
Dmitry Popov
79af8fb601 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 17:31:09 +02:00
Dmitry Popov
f9f00faa0e fix(Core): Added check for offline characters timeouts 2025-06-07 17:31:05 +02:00
CI
a3c41e84e4 chore: release version v1.66.18 2025-06-07 14:55:06 +00:00
Dmitry Popov
7f21f33351 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 16:54:40 +02:00
Dmitry Popov
568f682cee chore: release version v1.66.16 2025-06-07 16:54:36 +02:00
CI
901c4c8ca4 chore: release version v1.66.17 2025-06-07 14:44:50 +00:00
Dmitry Popov
3dbba97f9c fix(Core): Increased tracking pause timeout for offline characters up to 10 hours 2025-06-07 16:44:18 +02:00
CI
3475620267 chore: release version v1.66.16 2025-06-07 13:41:56 +00:00
Dmitry Popov
8936a5e5d8 chore: release version v1.66.15 2025-06-07 15:41:22 +02:00
Dmitry Popov
719e34f9bc fix(Core): Increased tracking pause timeout for offline characters up to 10 hours 2025-06-07 15:41:06 +02:00
Dmitry Popov
df955ff8b0 chore: release version v1.66.15 2025-06-07 13:57:25 +02:00
CI
4dc74022b4 chore: release version v1.66.15 2025-06-07 09:01:44 +00:00
Dmitry Popov
c2b7d07208 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 10:58:35 +02:00
Dmitry Popov
21e76a6f05 fix(Core): Added back arm docker image build 2025-06-07 10:58:24 +02:00
CI
89c0d6fad6 chore: release version v1.66.14 2025-06-07 08:48:05 +00:00
Dmitry Popov
b74d15b1ee Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 10:47:31 +02:00
Dmitry Popov
10313438bf fix(Core): fixed online updates 2025-06-07 10:47:28 +02:00
CI
a764217948 chore: release version v1.66.13 2025-06-07 07:49:31 +00:00
Dmitry Popov
d81d6fb937 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 09:48:56 +02:00
Dmitry Popov
4c0f7ab7f9 fix(Core): fixed location tracking issues 2025-06-07 09:48:53 +02:00
CI
1c48945a96 chore: release version v1.66.12
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-06 23:58:04 +00:00
Dmitry Popov
850901f62f Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 01:57:37 +02:00
Dmitry Popov
4822854e30 chore: release version v1.66.10 2025-06-07 01:57:32 +02:00
CI
f580538331 chore: release version v1.66.11 2025-06-06 23:47:37 +00:00
Dmitry Popov
0d70c555e6 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 01:47:07 +02:00
Dmitry Popov
c5f6cf0080 fix(Core): fixed refresh character tokens 2025-06-07 01:47:03 +02:00
CI
6ff7b3bc9a chore: release version v1.66.10
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-06 22:37:51 +00:00
Dmitry Popov
346c2c65b0 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 00:37:23 +02:00
Dmitry Popov
a6445fd500 chore: release version v1.66.8 2025-06-07 00:37:20 +02:00
CI
358e43e508 chore: release version v1.66.9 2025-06-06 22:23:05 +00:00
Dmitry Popov
20c5ba6b63 chore: release version v1.66.8 2025-06-07 00:22:35 +02:00
CI
661658a6e8 chore: release version v1.66.8 2025-06-06 21:32:10 +00:00
Dmitry Popov
0a6f224ed3 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-06 23:31:41 +02:00
Dmitry Popov
e7bb29693f fix: fixed disable detailed kills env check 2025-06-06 23:31:38 +02:00
CI
32dfd50461 chore: release version v1.66.7 2025-06-06 20:34:16 +00:00
Dmitry Popov
bfec385dce Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-06 22:33:49 +02:00
Dmitry Popov
04278f99d7 fix: fixed disable detailed kills env check 2025-06-06 22:33:46 +02:00
CI
9d3db19dc1 chore: release version v1.66.6 2025-06-06 20:03:06 +00:00
Dmitry Popov
3953e33f37 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-06 22:02:34 +02:00
Dmitry Popov
611fdd56d0 fix: respect error limits for ESI APIs 2025-06-06 22:02:31 +02:00
CI
36a4fd0f35 chore: release version v1.66.5 2025-06-06 17:13:49 +00:00
Dmitry Popov
488984a988 fix: respect error limits for ESI APIs 2025-06-06 19:13:07 +02:00
CI
1b183d6e58 chore: release version v1.66.4
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-06 12:52:02 +00:00
Dmitry Popov
3dcb6d30b5 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-06 14:51:27 +02:00
Dmitry Popov
1d11788f89 fix: respect error limits for ESI APIs 2025-06-06 14:51:24 +02:00
CI
d3822128ab chore: release version v1.66.3
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-05 22:58:55 +00:00
Dmitry Popov
6ac7836505 chore: release version v1.66.2 2025-06-06 00:58:24 +02:00
CI
5796fccae4 chore: release version v1.66.2 2025-06-05 18:53:11 +00:00
Dmitry Popov
22ab6e544c chore: release version v1.66.1 2025-06-05 20:43:28 +02:00
Dmitry Popov
5e735ab8bd chore: release version v1.66.1 2025-06-05 20:27:05 +02:00
Dmitry Popov
450139402d chore: release version v1.66.1 2025-06-05 20:26:49 +02:00
CI
1e0d4f1fde chore: release version v1.66.1 2025-06-05 15:28:12 +00:00
Dmitry Popov
7e9b1af3a3 Merge pull request #420 from guarzo/guarzo/sigfx
fix: remove bugs with signature deletion
2025-06-05 19:27:46 +04:00
Guarzo
30b90cd4be fix: remove bugs with signature deletion 2025-06-05 10:15:52 -04:00
CI
f28affa222 chore: release version v1.66.0
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-05 09:23:21 +00:00
Dmitry Popov
2ae7b187b8 Merge pull request #418 from wanderer-industries/develop
Develop
2025-06-05 13:22:54 +04:00
Dmitry Popov
ad037be1f4 Merge branch 'main' into develop 2025-06-05 11:09:19 +02:00
CI
9e31542c5f chore: release version v1.65.24
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-04 18:57:47 +00:00
Dmitry Popov
aae6ed0cb3 fix(Core): Fixed errors duration check to reduce requests amount to ESI 2025-06-04 20:57:17 +02:00
Dmitry Popov
7ea2ecb8e9 Merge pull request #417 from guarzo/guarzo/deleting
feat: show deleted signatures during undo timer
2025-06-04 22:30:59 +04:00
guarzo
852fc28896 Merge branch 'develop' into guarzo/deleting 2025-06-04 13:04:12 -04:00
Guarzo
fcdab79802 fix: remove callbacks from effect dependencies 2025-06-04 13:04:00 -04:00
CI
bb0e06589f chore: release version v1.65.23 2025-06-04 15:53:50 +00:00
Dmitry Popov
d65b72c4dd fix(Core): Added back arm docker image build 2025-06-04 17:53:21 +02:00
CI
24a3d5b3de chore: release version v1.65.22 2025-06-04 15:44:34 +00:00
Dmitry Popov
2814b46941 fix(Core): Fix character tracking issues 2025-06-04 17:43:53 +02:00
Guarzo
6ffc25448d feat: show deleted signatures during undo timer 2025-06-03 21:57:04 -04:00
CI
d9a82f7c9f chore: release version v1.65.21
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-01 19:00:52 +00:00
Dmitry Popov
9a8106947e Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-01 21:00:23 +02:00
Dmitry Popov
e21ca79ea1 fix(Core): Fix connection pool errors 2025-06-01 21:00:14 +02:00
CI
dd579caeac chore: release version v1.65.20 2025-06-01 17:56:46 +00:00
Dmitry Popov
ddf8a4b9fb Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-01 19:56:18 +02:00
Dmitry Popov
3c04f4194e fix(Core): fix waypoint set timeout errors 2025-06-01 19:56:14 +02:00
CI
1e0de841eb chore: release version v1.65.19
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-01 08:15:49 +00:00
Dmitry Popov
c9c88cf0a6 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-01 10:15:21 +02:00
Dmitry Popov
fd1e124166 fix(Core): fix updating character online 2025-06-01 10:15:18 +02:00
CI
aa2bee258a chore: release version v1.65.18
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-30 21:38:38 +00:00
Dmitry Popov
12d696dc07 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-30 23:38:10 +02:00
Dmitry Popov
b33772a1d6 fix(Core): fix updating systems and connections 2025-05-30 23:38:07 +02:00
CI
b41f89d7de chore: release version v1.65.17
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-29 15:38:24 +00:00
Dmitry Popov
e8ca213b74 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-29 17:37:51 +02:00
Dmitry Popov
7620b8d493 fix(Core): fix updating systems and connections 2025-05-29 17:37:47 +02:00
Dmitry Popov
23306fd9e3 fix(Comments): fix error loading comments 2025-05-29 17:36:45 +02:00
CI
a68ccdca50 chore: release version v1.65.16
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-29 09:10:07 +00:00
Dmitry Popov
771e432546 Merge pull request #415 from wanderer-industries/wnd-414-allow-lock
fix(Map): Allow lock systems for members
2025-05-29 13:09:35 +04:00
DanSylvest
20bdbfb81a fix(Map): Allow lock systems for members
wnd-414
2025-05-29 09:05:43 +03:00
CI
90729b436c chore: release version v1.65.15
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-28 10:25:50 +00:00
Dmitry Popov
8ea4e97bbf Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-28 12:25:23 +02:00
Dmitry Popov
17e12e9263 chore: got rid of timestamp checking on server 2025-05-28 12:25:19 +02:00
CI
4cb3d021f4 chore: release version v1.65.14 2025-05-28 09:29:39 +00:00
Dmitry Popov
97cec2e127 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-28 11:28:55 +02:00
Dmitry Popov
9c4294659c chore: got rid of timestamp checking on UI 2025-05-28 11:28:50 +02:00
CI
5b8526db96 chore: release version v1.65.13 2025-05-28 09:28:10 +00:00
Dmitry Popov
54cce9e9fb Merge pull request #412 from alpha02x/fix-small-sigs
Fix: small wh size is now passed from signature to connection
2025-05-28 13:27:45 +04:00
alpha02x
54d1691d19 fix(Signatures): small wh size is now passed from signature to connection 2025-05-28 07:52:46 +00:00
CI
4d4431868e chore: release version v1.65.12
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-27 14:47:31 +00:00
Dmitry Popov
cdae69d346 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-27 16:47:02 +02:00
Dmitry Popov
3e86baabd8 fix(Map): Fixed showing character ship 2025-05-27 16:46:59 +02:00
CI
6ec92b19fb chore: release version v1.65.11 2025-05-27 11:53:48 +00:00
Dmitry Popov
630caa8686 fix(Map): Fixed showing character ship 2025-05-27 13:53:17 +02:00
CI
497c3b2165 chore: release version v1.65.10
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-27 07:43:27 +00:00
Dmitry Popov
8823d06893 Merge pull request #408 from wanderer-industries/pings
Rally Point.
2025-05-27 11:42:53 +04:00
DanSylvest
72a2bf50df fix(Map): Fixed sorting for characters in Local 2025-05-27 09:14:32 +03:00
DanSylvest
15c1ed2011 Merge remote-tracking branch 'origin/pings' into pings 2025-05-27 09:10:39 +03:00
DanSylvest
3fb19663cc fix(Map): Rally: fixed conflict style of status and rally 2025-05-27 09:10:17 +03:00
Dmitry Popov
00cdbbc89c Merge branch 'main' into pings 2025-05-26 22:24:37 +02:00
CI
07f3cec16d chore: release version v1.65.9
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-26 18:14:43 +00:00
Dmitry Popov
e893e25ff4 chore: release version v1.65.8 2025-05-26 20:14:09 +02:00
Dmitry Popov
1ad9a1eb13 Merge branch 'main' into pings 2025-05-26 19:04:22 +02:00
Dmitry Popov
d9288596e8 chore: release version v1.65.8
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-26 18:39:11 +02:00
CI
a2a642d9ce chore: release version v1.65.8 2025-05-26 15:33:17 +00:00
Dmitry Popov
4f00007108 chore: release version v1.65.7 2025-05-26 17:32:43 +02:00
Dmitry Popov
816ee77b6f fix(Core): Fixed character token refresh 2025-05-26 17:30:54 +02:00
Dmitry Popov
26d470ecda Merge branch 'main' into pings 2025-05-26 16:59:54 +02:00
Dmitry Popov
3babd9d95e chore: release version v1.65.7 2025-05-26 16:18:06 +02:00
CI
802e81b1cd chore: release version v1.65.7 2025-05-26 14:05:57 +00:00
Dmitry Popov
41f0834c51 chore: release version v1.65.6 2025-05-26 16:05:12 +02:00
Dmitry Popov
880de0b047 chore: release version v1.65.6 2025-05-26 15:57:34 +02:00
Dmitry Popov
bbe7fda4e0 fix(Core): Fixed map character tracking issues 2025-05-26 15:56:46 +02:00
Dmitry Popov
4fd214e328 Merge branch 'main' into pings 2025-05-26 12:35:04 +02:00
CI
92a9274dce chore: release version v1.65.6 2025-05-26 10:19:27 +00:00
Dmitry Popov
8765d83083 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-26 12:09:13 +02:00
Dmitry Popov
a298152bc8 fix(Core): Fixed map character tracking issues 2025-05-26 12:09:09 +02:00
CI
2b7abe5774 chore: release version v1.65.5
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-26 00:11:32 +00:00
Dmitry Popov
3e9241892e fix(Core): Fixed map character tracking issues 2025-05-26 01:41:21 +02:00
DanSylvest
a8dcdcf339 fix(Map): Add Rally point. Change placement of settings in Map User Settings. Add ability to placement minimap. 2025-05-25 18:56:57 +03:00
Dmitry Popov
6ea79a7960 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-25 09:41:39 +02:00
Dmitry Popov
2af562e313 fix(Signature): Update restored signature character 2025-05-25 09:41:33 +02:00
CI
40672f6a47 chore: release version v1.65.4 2025-05-24 17:30:03 +00:00
Dmitry Popov
6d66ae3f50 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-24 19:18:57 +02:00
Dmitry Popov
94c89e0325 fix(Signature): Force signature update even if there are no any changes 2025-05-24 19:18:50 +02:00
CI
3670ef40a3 chore: release version v1.65.3 2025-05-23 18:29:03 +00:00
Dmitry Popov
16d464fba5 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-23 20:06:20 +02:00
Dmitry Popov
0b7e0b9cd0 fix(Signature): Fixed signature clenup 2025-05-23 20:06:17 +02:00
CI
dd5fd114d2 chore: release version v1.65.2 2025-05-23 15:33:00 +00:00
Dmitry Popov
6e53879344 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-23 17:24:33 +02:00
Dmitry Popov
af2bfd4d59 fix(Signature): Fixed signature updates 2025-05-23 17:24:30 +02:00
CI
a4a34c8ba7 chore: release version v1.65.1
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-22 11:47:01 +00:00
Dmitry Popov
8c609f4fdf Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-22 11:52:23 +02:00
Dmitry Popov
197f5b583f fix(Core): Added unsync map events timeout handling (force page refresh if outdated map events found) 2025-05-22 11:52:20 +02:00
CI
4eb4a03e59 chore: release version v1.65.0 2025-05-22 09:45:26 +00:00
Dmitry Popov
5719469452 chore(Map): Don't cleanup systems with active pings 2025-05-22 10:33:22 +02:00
Dmitry Popov
6e9d525890 chore(Map): Don't cleanup systems with active pings 2025-05-22 10:30:53 +02:00
Dmitry Popov
e82805dd48 Merge branch 'main' into pings 2025-05-22 09:40:24 +02:00
Dmitry Popov
3d4e66d438 Merge pull request #399 from guarzo/guarzo/moreopenapi
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
fix: remove required id field from character schema
2025-05-21 20:07:32 +04:00
Guarzo
ffbc9f169a fix: remove required id field from character schema 2025-05-21 11:59:03 -04:00
Dmitry Popov
99650187e9 Merge pull request #397 from guarzo/guarzo/c1fix
fix: correct issue with connection types between connected k-space systems
2025-05-21 17:47:21 +04:00
Guarzo
92699317cd fix: update openapi spec response types 2025-05-21 09:19:12 -04:00
Guarzo
0e48315803 fix: fix issue with connection generation between k-space 2025-05-21 09:19:12 -04:00
Dmitry Popov
868ec246bd Merge pull request #395 from wanderer-industries/develop
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
Develop
2025-05-21 15:39:01 +04:00
Dmitry Popov
0030a688c6 Merge branch 'develop' of github.com:wanderer-industries/wanderer into develop 2025-05-21 11:52:18 +02:00
Dmitry Popov
3ba8f51a2f fix(Signature): Fixed signatures updates 2025-05-21 11:52:15 +02:00
Dmitry Popov
04576b335c Merge pull request #392 from guarzo/guarzo/c1qol
feat: default c1 connections to medium
2025-05-21 13:12:04 +04:00
Dmitry Popov
ea29aa176f Merge branch 'main' into develop 2025-05-21 08:46:48 +02:00
CI
9a9b7289ba chore: release version v1.64.8
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-20 14:33:21 +00:00
Dmitry Popov
5edcd5572a Merge branch 'main' into pings 2025-05-20 16:08:58 +02:00
Dmitry Popov
d601790864 fix(Core): Added unsync map events timeout handling (force page refresh if outdated map events found) 2025-05-20 16:08:43 +02:00
Dmitry Popov
3cd9b819f5 chore(Map): Added ping system to routes 2025-05-20 15:31:38 +02:00
Dmitry Popov
bf58d3ae93 Merge branch 'main' into develop 2025-05-20 11:24:46 +02:00
Guarzo
d6c32e2d39 feat: default connections from c1 holes to medium size 2025-05-20 04:39:17 -04:00
Dmitry Popov
6914f75bb7 chore(Map): Added pings clean-up logic 2025-05-20 00:03:28 +02:00
Dmitry Popov
3adf3946b5 chore(Map): Added pings CRUD map api 2025-05-19 21:23:06 +02:00
Dmitry Popov
bdc4948afb Merge pull request #366 from guarzo/guarzo/undo
feat: improve signature undo process
2025-05-19 22:44:13 +04:00
Guarzo
331db10029 fix: update openapi spec for other apis 2025-05-19 11:35:15 -04:00
Dmitry Popov
c036a157c8 Merge branch 'main' into pings 2025-05-19 15:30:17 +02:00
Dmitry Popov
2daf9e34d2 chore: release version v1.64.7
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-19 15:30:06 +02:00
achichenkov
acf35f8c51 fix(Map): Routes - hide user routes btn from context if subscriptions is not active or widget is closed. Also now hidden widget will show again in place where it was on moment of hide (except cases when screen size has changed. 2025-05-17 09:22:34 +03:00
achichenkov
9155515082 fix(Map): PINGS - Rally point first prototype 2025-05-16 11:18:28 +03:00
CI
558cd9b8b3 chore: release version v1.64.7
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-15 21:40:47 +00:00
Dmitry Popov
a0f02d0d2f Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-15 23:15:10 +02:00
Dmitry Popov
9feb8492aa fix(Core): Fixed connection EOL time refreshed every 2 minutes 2025-05-15 23:15:07 +02:00
CI
e5aa726899 chore: release version v1.64.6
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-15 10:23:04 +00:00
Dmitry Popov
93d1c28ccd Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-15 12:02:02 +02:00
Dmitry Popov
b5ba9200bc fix(Core): Added map hubs limits checking & a proper warning message shown 2025-05-15 12:01:59 +02:00
CI
699d866670 chore: release version v1.64.5
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-14 22:13:32 +00:00
Dmitry Popov
c3071344cb chore: Added link to YT channel 2025-05-14 23:59:06 +02:00
Dmitry Popov
9e998dd2b6 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-14 23:24:57 +02:00
Dmitry Popov
c9accf6079 fix(Core): Added character name update on re-auth 2025-05-14 23:24:49 +02:00
CI
1b41a51004 chore: release version v1.64.4 2025-05-14 20:49:45 +00:00
guarzo
3338dce900 Merge branch 'develop' into guarzo/undo 2025-05-14 15:04:42 -04:00
Guarzo
1364779f81 feat: support german and french signatures 2025-05-14 10:38:18 -04:00
Dmitry Popov
b49d3423fc fix(Core): Added 1 min timeout for ship and location updates on ESI API errors
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-14 16:35:21 +02:00
CI
cccab2a985 chore: release version v1.64.3 2025-05-14 10:14:49 +00:00
Dmitry Popov
1abaa90a7d Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-14 11:54:41 +02:00
Dmitry Popov
6e1993ca8a fix(Core): Fixed character tracking initialization logic & removed search caching 2025-05-14 11:54:37 +02:00
CI
171c821ac4 chore: release version v1.64.2
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-13 21:51:53 +00:00
Dmitry Popov
7ebf9186bf Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-13 23:42:32 +02:00
Dmitry Popov
57d2f2baef fix(Core): Fixed tracking of ship & location for offline characters 2025-05-13 23:42:30 +02:00
CI
0aee13878a chore: release version v1.64.1 2025-05-13 19:40:55 +00:00
Dmitry Popov
f93ef0ca76 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-13 21:31:06 +02:00
Dmitry Popov
4ec03d8338 fix(Core): Fixed tracking stopped due to server errors 2025-05-13 21:31:02 +02:00
guarzo
cb318aa6c6 Merge branch 'develop' into guarzo/undo 2025-05-13 12:35:11 -04:00
CI
733482cd5c chore: release version v1.64.0
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-13 10:42:59 +00:00
Dmitry Popov
3969d1287d fix(Core): Fixed EOL connections cleanup 2025-05-13 12:26:58 +02:00
Dmitry Popov
1aa7854b0d chore: Added ESI API cached responces based on expire headers 2025-05-13 12:08:06 +02:00
Dmitry Popov
7b27d4a1a7 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-13 11:09:39 +02:00
Dmitry Popov
24ddb8771f fix(Core): Avoid Zarzakh system in routes widget 2025-05-13 11:09:35 +02:00
Dmitry Popov
7134714245 Merge pull request #376 from wanderer-industries/develop
Develop
2025-05-13 13:02:47 +04:00
guarzo
96b320ac26 fix: remove repeat errors for token refresh (#375) 2025-05-13 13:01:05 +04:00
Dmitry Popov
61235828ce chore: release version v1.62.1 2025-05-13 09:07:19 +02:00
guarzo
1a27b21efe Merge branch 'develop' into guarzo/undo 2025-05-12 11:55:19 -04:00
guarzo
b88e121b30 fix: updated openapi spec for character activity (#374) 2025-05-12 19:09:18 +04:00
guarzo
4ba4119c2b fix: removed error from characters endpoint, and updated routes (#372) 2025-05-12 11:15:20 +04:00
Dmitry Popov
91d1ca201c Merge branch 'main' into develop 2025-05-11 14:35:53 +02:00
guarzo
8bf063a228 fix: cleanup examples for system and connections (#370) 2025-05-11 16:20:23 +04:00
CI
4f53de39b1 chore: release version v1.63.0
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-11 12:17:06 +00:00
Dmitry Popov
8c3804f107 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-11 14:03:57 +02:00
Dmitry Popov
1be4ec2b90 feat(Core): Updated map active characters page 2025-05-11 14:03:53 +02:00
Dmitry Popov
8f0ed44b11 chore: release version v1.62.3 2025-05-10 20:46:01 +02:00
CI
cbadfc4ac4 chore: release version v1.62.4
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-10 12:08:58 +00:00
Dmitry Popov
3d88ae4452 fix(Core): Fixed map characters got untracked 2025-05-10 13:46:49 +02:00
guarzo
e57f565812 Merge branch 'develop' into guarzo/undo 2025-05-09 18:59:46 -04:00
Guarzo
da2605ee03 feat: improve signature undo process 2025-05-09 18:59:33 -04:00
Dmitry Popov
07e2196eb4 Merge branch 'main' into develop 2025-05-09 14:02:39 +02:00
CI
6d99c54af7 chore: release version v1.62.3
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-08 12:14:20 +00:00
Dmitry Popov
2b7901e9a8 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-08 12:20:14 +02:00
Dmitry Popov
fb06dd1dbc fix(Core): Fixed map characters got untracked 2025-05-08 12:20:09 +02:00
guarzo
d3b825529e fix: remove error on websocket reconnect (#367) 2025-05-07 12:24:17 +04:00
guarzo
ccf9c0db22 feat (api): add additional structure/signature methods (#365) 2025-05-06 20:42:47 +04:00
CI
f8ba36b8be chore: release version v1.62.2
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-05 18:51:41 +00:00
achichenkov
927c07bfd5 Merge branch 'refs/heads/main' into pings 2025-05-05 21:49:15 +03:00
Dmitry Popov
5bf9d99b3d Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-05 20:32:17 +02:00
Dmitry Popov
7cad05342a fix(Core): Fixed audit export API 2025-05-05 20:32:14 +02:00
CI
867780e525 chore: release version v1.62.1
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-05-05 09:14:15 +00:00
Dmitry Popov
ff4f9a79c9 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-05-05 10:18:44 +02:00
Dmitry Popov
6699c36fb3 chore: load user roads for map with active subscription only 2025-05-05 10:18:41 +02:00
Dmitry Popov
d00caf1f4c Merge branch 'pings' of github.com:wanderer-industries/wanderer into pings 2025-05-04 11:12:34 +02:00
Dmitry Popov
a5e9d72bc5 chore: added pings repo 2025-05-04 11:12:30 +02:00
achichenkov
8ac9047831 Merge branch 'refs/heads/main' into pings 2025-05-04 11:40:03 +03:00
Dmitry Popov
65509ace59 chore: added ping events broadcasts 2025-05-03 20:28:51 +02:00
Dmitry Popov
ea173f971a Merge branch 'main' into pings 2025-05-03 19:45:07 +02:00
guarzo
6378754c57 feat (api): add additional system/connections methods (#351) 2025-05-03 19:41:21 +04:00
Dmitry Popov
c45c97c5d8 chore: added base map pings data 2025-04-24 13:22:03 +02:00
209 changed files with 15649 additions and 3865 deletions

View File

@@ -18,49 +18,8 @@ permissions:
contents: write
jobs:
deploy-test:
name: 🚀 Deploy to test env (fly.io)
runs-on: ubuntu-latest
if: ${{ github.base_ref == 'main' || (github.ref == 'refs/heads/main' && github.event_name == 'push') }}
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
- uses: superfly/flyctl-actions/setup-flyctl@master
- name: 👀 Read app name
uses: SebRollen/toml-action@v1.0.0
id: app_name
with:
file: "fly.toml"
field: "app"
- name: 🚀 Deploy Test
run: flyctl deploy --remote-only --wait-timeout=300 --ha=false
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
manual-approval:
name: Manual Approval
runs-on: ubuntu-latest
needs: deploy-test
if: success()
permissions:
issues: write
steps:
- name: Await Manual Approval
uses: trstringer/manual-approval@v1
with:
secret: ${{ github.TOKEN }}
approvers: DmitryPopov
minimum-approvals: 1
issue-title: "Manual Approval Required for Release"
issue-body: "Please approve or deny the deployment."
build:
name: 🛠 Build
needs: manual-approval
runs-on: ubuntu-22.04
if: ${{ (github.ref == 'refs/heads/main') && github.event_name == 'push' }}
permissions:
@@ -157,7 +116,6 @@ jobs:
matrix:
platform:
- linux/amd64
- linux/arm64
steps:
- name: Prepare
run: |

View File

@@ -2,6 +2,620 @@
<!-- changelog -->
## [v1.67.4](https://github.com/wanderer-industries/wanderer/compare/v1.67.3...v1.67.4) (2025-06-08)
### Bug Fixes:
* Core: Fixed issue with system splash updates
## [v1.67.3](https://github.com/wanderer-industries/wanderer/compare/v1.67.2...v1.67.3) (2025-06-08)
### Bug Fixes:
* Core: Fixed issue with system splash updates
## [v1.67.2](https://github.com/wanderer-industries/wanderer/compare/v1.67.1...v1.67.2) (2025-06-08)
## [v1.67.1](https://github.com/wanderer-industries/wanderer/compare/v1.67.0...v1.67.1) (2025-06-08)
## [v1.67.0](https://github.com/wanderer-industries/wanderer/compare/v1.66.25...v1.67.0) (2025-06-08)
### Features:
* Core: Added support for WANDERER_CHARACTER_TRACKING_PAUSE_DISABLED env variable to pause inactive character trackers
## [v1.66.25](https://github.com/wanderer-industries/wanderer/compare/v1.66.24...v1.66.25) (2025-06-08)
### Bug Fixes:
* Core: Disabled kills fetching based on env settings
## [v1.66.24](https://github.com/wanderer-industries/wanderer/compare/v1.66.23...v1.66.24) (2025-06-08)
## [v1.66.23](https://github.com/wanderer-industries/wanderer/compare/v1.66.22...v1.66.23) (2025-06-08)
## [v1.66.22](https://github.com/wanderer-industries/wanderer/compare/v1.66.21...v1.66.22) (2025-06-07)
## [v1.66.21](https://github.com/wanderer-industries/wanderer/compare/v1.66.20...v1.66.21) (2025-06-07)
### Bug Fixes:
* Core: Fixed kills fetching based on env settings
## [v1.66.20](https://github.com/wanderer-industries/wanderer/compare/v1.66.19...v1.66.20) (2025-06-07)
## [v1.66.19](https://github.com/wanderer-industries/wanderer/compare/v1.66.18...v1.66.19) (2025-06-07)
### Bug Fixes:
* Core: Added check for offline characters timeouts
## [v1.66.18](https://github.com/wanderer-industries/wanderer/compare/v1.66.17...v1.66.18) (2025-06-07)
## [v1.66.17](https://github.com/wanderer-industries/wanderer/compare/v1.66.16...v1.66.17) (2025-06-07)
### Bug Fixes:
* Core: Increased tracking pause timeout for offline characters up to 10 hours
## [v1.66.16](https://github.com/wanderer-industries/wanderer/compare/v1.66.15...v1.66.16) (2025-06-07)
### Bug Fixes:
* Core: Increased tracking pause timeout for offline characters up to 10 hours
## [v1.66.15](https://github.com/wanderer-industries/wanderer/compare/v1.66.14...v1.66.15) (2025-06-07)
### Bug Fixes:
* Core: Added back arm docker image build
## [v1.66.14](https://github.com/wanderer-industries/wanderer/compare/v1.66.13...v1.66.14) (2025-06-07)
### Bug Fixes:
* Core: fixed online updates
## [v1.66.13](https://github.com/wanderer-industries/wanderer/compare/v1.66.12...v1.66.13) (2025-06-07)
### Bug Fixes:
* Core: fixed location tracking issues
## [v1.66.12](https://github.com/wanderer-industries/wanderer/compare/v1.66.11...v1.66.12) (2025-06-06)
## [v1.66.11](https://github.com/wanderer-industries/wanderer/compare/v1.66.10...v1.66.11) (2025-06-06)
### Bug Fixes:
* Core: fixed refresh character tokens
## [v1.66.10](https://github.com/wanderer-industries/wanderer/compare/v1.66.9...v1.66.10) (2025-06-06)
## [v1.66.9](https://github.com/wanderer-industries/wanderer/compare/v1.66.8...v1.66.9) (2025-06-06)
## [v1.66.8](https://github.com/wanderer-industries/wanderer/compare/v1.66.7...v1.66.8) (2025-06-06)
### Bug Fixes:
* fixed disable detailed kills env check
## [v1.66.7](https://github.com/wanderer-industries/wanderer/compare/v1.66.6...v1.66.7) (2025-06-06)
### Bug Fixes:
* fixed disable detailed kills env check
## [v1.66.6](https://github.com/wanderer-industries/wanderer/compare/v1.66.5...v1.66.6) (2025-06-06)
### Bug Fixes:
* respect error limits for ESI APIs
## [v1.66.5](https://github.com/wanderer-industries/wanderer/compare/v1.66.4...v1.66.5) (2025-06-06)
### Bug Fixes:
* respect error limits for ESI APIs
## [v1.66.4](https://github.com/wanderer-industries/wanderer/compare/v1.66.3...v1.66.4) (2025-06-06)
### Bug Fixes:
* respect error limits for ESI APIs
## [v1.66.3](https://github.com/wanderer-industries/wanderer/compare/v1.66.2...v1.66.3) (2025-06-05)
## [v1.66.2](https://github.com/wanderer-industries/wanderer/compare/v1.66.1...v1.66.2) (2025-06-05)
## [v1.66.1](https://github.com/wanderer-industries/wanderer/compare/v1.66.0...v1.66.1) (2025-06-05)
### Bug Fixes:
* remove bugs with signature deletion
## [v1.66.0](https://github.com/wanderer-industries/wanderer/compare/v1.65.24...v1.66.0) (2025-06-05)
### Features:
* show deleted signatures during undo timer
### Bug Fixes:
* remove callbacks from effect dependencies
## [v1.65.24](https://github.com/wanderer-industries/wanderer/compare/v1.65.23...v1.65.24) (2025-06-04)
### Bug Fixes:
* Core: Fixed errors duration check to reduce requests amount to ESI
## [v1.65.23](https://github.com/wanderer-industries/wanderer/compare/v1.65.22...v1.65.23) (2025-06-04)
### Bug Fixes:
* Core: Added back arm docker image build
## [v1.65.22](https://github.com/wanderer-industries/wanderer/compare/v1.65.21...v1.65.22) (2025-06-04)
### Bug Fixes:
* Core: Fix character tracking issues
## [v1.65.21](https://github.com/wanderer-industries/wanderer/compare/v1.65.20...v1.65.21) (2025-06-01)
### Bug Fixes:
* Core: Fix connection pool errors
## [v1.65.20](https://github.com/wanderer-industries/wanderer/compare/v1.65.19...v1.65.20) (2025-06-01)
### Bug Fixes:
* Core: fix waypoint set timeout errors
## [v1.65.19](https://github.com/wanderer-industries/wanderer/compare/v1.65.18...v1.65.19) (2025-06-01)
### Bug Fixes:
* Core: fix updating character online
## [v1.65.18](https://github.com/wanderer-industries/wanderer/compare/v1.65.17...v1.65.18) (2025-05-30)
### Bug Fixes:
* Core: fix updating systems and connections
## [v1.65.17](https://github.com/wanderer-industries/wanderer/compare/v1.65.16...v1.65.17) (2025-05-29)
### Bug Fixes:
* Core: fix updating systems and connections
* Comments: fix error loading comments
## [v1.65.16](https://github.com/wanderer-industries/wanderer/compare/v1.65.15...v1.65.16) (2025-05-29)
### Bug Fixes:
* Map: Allow lock systems for members
## [v1.65.15](https://github.com/wanderer-industries/wanderer/compare/v1.65.14...v1.65.15) (2025-05-28)
## [v1.65.14](https://github.com/wanderer-industries/wanderer/compare/v1.65.13...v1.65.14) (2025-05-28)
## [v1.65.13](https://github.com/wanderer-industries/wanderer/compare/v1.65.12...v1.65.13) (2025-05-28)
### Bug Fixes:
* Signatures: small wh size is now passed from signature to connection
## [v1.65.12](https://github.com/wanderer-industries/wanderer/compare/v1.65.11...v1.65.12) (2025-05-27)
### Bug Fixes:
* Map: Fixed showing character ship
## [v1.65.11](https://github.com/wanderer-industries/wanderer/compare/v1.65.10...v1.65.11) (2025-05-27)
### Bug Fixes:
* Map: Fixed showing character ship
## [v1.65.10](https://github.com/wanderer-industries/wanderer/compare/v1.65.9...v1.65.10) (2025-05-27)
### Bug Fixes:
* Map: Fixed sorting for characters in Local
* Map: Rally: fixed conflict style of status and rally
* Core: Fixed character token refresh
* Map: Add Rally point. Change placement of settings in Map User Settings. Add ability to placement minimap.
* Map: Routes - hide user routes btn from context if subscriptions is not active or widget is closed. Also now hidden widget will show again in place where it was on moment of hide (except cases when screen size has changed.
* Map: PINGS - Rally point first prototype
## [v1.65.9](https://github.com/wanderer-industries/wanderer/compare/v1.65.8...v1.65.9) (2025-05-26)
## [v1.65.8](https://github.com/wanderer-industries/wanderer/compare/v1.65.7...v1.65.8) (2025-05-26)
## [v1.65.7](https://github.com/wanderer-industries/wanderer/compare/v1.65.6...v1.65.7) (2025-05-26)
### Bug Fixes:
* Core: Fixed map character tracking issues
## [v1.65.6](https://github.com/wanderer-industries/wanderer/compare/v1.65.5...v1.65.6) (2025-05-26)
### Bug Fixes:
* Core: Fixed map character tracking issues
## [v1.65.5](https://github.com/wanderer-industries/wanderer/compare/v1.65.4...v1.65.5) (2025-05-26)
### Bug Fixes:
* Core: Fixed map character tracking issues
* Signature: Update restored signature character
## [v1.65.4](https://github.com/wanderer-industries/wanderer/compare/v1.65.3...v1.65.4) (2025-05-24)
### Bug Fixes:
* Signature: Force signature update even if there are no any changes
## [v1.65.3](https://github.com/wanderer-industries/wanderer/compare/v1.65.2...v1.65.3) (2025-05-23)
### Bug Fixes:
* Signature: Fixed signature clenup
## [v1.65.2](https://github.com/wanderer-industries/wanderer/compare/v1.65.1...v1.65.2) (2025-05-23)
### Bug Fixes:
* Signature: Fixed signature updates
## [v1.65.1](https://github.com/wanderer-industries/wanderer/compare/v1.65.0...v1.65.1) (2025-05-22)
### Bug Fixes:
* Core: Added unsync map events timeout handling (force page refresh if outdated map events found)
## [v1.65.0](https://github.com/wanderer-industries/wanderer/compare/v1.64.8...v1.65.0) (2025-05-22)
### Features:
* default connections from c1 holes to medium size
* support german and french signatures
* improve signature undo process
### Bug Fixes:
* remove required id field from character schema
* update openapi spec response types
* fix issue with connection generation between k-space
* Signature: Fixed signatures updates
* update openapi spec for other apis
## [v1.64.8](https://github.com/wanderer-industries/wanderer/compare/v1.64.7...v1.64.8) (2025-05-20)
### Bug Fixes:
* Core: Added unsync map events timeout handling (force page refresh if outdated map events found)
## [v1.64.7](https://github.com/wanderer-industries/wanderer/compare/v1.64.6...v1.64.7) (2025-05-15)
### Bug Fixes:
* Core: Fixed connection EOL time refreshed every 2 minutes
## [v1.64.6](https://github.com/wanderer-industries/wanderer/compare/v1.64.5...v1.64.6) (2025-05-15)
### Bug Fixes:
* Core: Added map hubs limits checking & a proper warning message shown
## [v1.64.5](https://github.com/wanderer-industries/wanderer/compare/v1.64.4...v1.64.5) (2025-05-14)
### Bug Fixes:
* Core: Added character name update on re-auth
## [v1.64.4](https://github.com/wanderer-industries/wanderer/compare/v1.64.3...v1.64.4) (2025-05-14)
### Bug Fixes:
* Core: Added 1 min timeout for ship and location updates on ESI API errors
## [v1.64.3](https://github.com/wanderer-industries/wanderer/compare/v1.64.2...v1.64.3) (2025-05-14)
### Bug Fixes:
* Core: Fixed character tracking initialization logic & removed search caching
## [v1.64.2](https://github.com/wanderer-industries/wanderer/compare/v1.64.1...v1.64.2) (2025-05-13)
### Bug Fixes:
* Core: Fixed tracking of ship & location for offline characters
## [v1.64.1](https://github.com/wanderer-industries/wanderer/compare/v1.64.0...v1.64.1) (2025-05-13)
### Bug Fixes:
* Core: Fixed tracking stopped due to server errors
## [v1.64.0](https://github.com/wanderer-industries/wanderer/compare/v1.63.0...v1.64.0) (2025-05-13)
### Features:
* api: add additional structure/signature methods (#365)
* api: add additional system/connections methods (#351)
### Bug Fixes:
* Core: Fixed EOL connections cleanup
* Core: Avoid Zarzakh system in routes widget
* remove repeat errors for token refresh (#375)
* updated openapi spec for character activity (#374)
* removed error from characters endpoint, and updated routes (#372)
* cleanup examples for system and connections (#370)
* remove error on websocket reconnect (#367)
## [v1.63.0](https://github.com/wanderer-industries/wanderer/compare/v1.62.4...v1.63.0) (2025-05-11)
### Features:
* Core: Updated map active characters page
## [v1.62.4](https://github.com/wanderer-industries/wanderer/compare/v1.62.3...v1.62.4) (2025-05-10)
### Bug Fixes:
* Core: Fixed map characters got untracked
## [v1.62.3](https://github.com/wanderer-industries/wanderer/compare/v1.62.2...v1.62.3) (2025-05-08)
### Bug Fixes:
* Core: Fixed map characters got untracked
## [v1.62.2](https://github.com/wanderer-industries/wanderer/compare/v1.62.1...v1.62.2) (2025-05-05)
### Bug Fixes:
* Core: Fixed audit export API
## [v1.62.1](https://github.com/wanderer-industries/wanderer/compare/v1.62.0...v1.62.1) (2025-05-05)
## [v1.62.0](https://github.com/wanderer-industries/wanderer/compare/v1.61.2...v1.62.0) (2025-05-05)

View File

@@ -17,5 +17,6 @@ module.exports = {
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'react/react-in-jsx-scope': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
"linebreak-style": "off",
},
};

View File

@@ -7,5 +7,5 @@
"semi": true,
"tabWidth": 2,
"useTabs": false,
"endOfLine": "lf"
"endOfLine": "auto"
}

View File

@@ -198,3 +198,17 @@
}
}
.p-autocomplete .p-autocomplete-multiple-container:not(.p-disabled).p-focus {
box-shadow: 0 0 0 1px #335c7e;
border-color: #335c7e;
}
.p-inputtext:enabled:focus {
box-shadow: 0 0 0 1px #335c7e;
border-color: #335c7e;
}
.p-inputtext:enabled:hover {
border-color: #335c7e;
}

View File

@@ -1,14 +1,13 @@
import { useCallback } from 'react';
import clsx from 'clsx';
import { useAutoAnimate } from '@formkit/auto-animate/react';
import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts';
import { CharacterTypeRaw } from '@/hooks/Mapper/types';
import { emitMapEvent } from '@/hooks/Mapper/events';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import classes from './Characters.module.scss';
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';
interface CharactersProps {
data: CharacterTypeRaw[];
}
@@ -17,13 +16,22 @@ export const Characters = ({ data }: CharactersProps) => {
const [parent] = useAutoAnimate();
const {
outCommand,
data: { mainCharacterEveId, followingCharacterEveId },
} = useMapRootState();
const handleSelect = useCallback((character: CharacterTypeRaw) => {
const handleSelect = useCallback(async (character: CharacterTypeRaw) => {
if (!character) {
return;
}
await outCommand({
type: OutCommand.startTracking,
data: { character_eve_id: character.eve_id },
});
emitMapEvent({
name: Commands.centerSystem,
data: character?.location?.solar_system_id?.toString(),
data: character.location?.solar_system_id?.toString(),
});
}, []);
@@ -37,14 +45,26 @@ export const Characters = ({ data }: CharactersProps) => {
className={clsx(
'overflow-hidden relative',
'flex w-[35px] h-[35px] rounded-[4px] border-[1px] border-solid bg-transparent cursor-pointer',
'transition-colors duration-250',
'transition-colors duration-250 hover:bg-stone-300/90',
{
['border-stone-800/90']: !character.online,
['border-lime-600/70']: character.online,
},
)}
title={character.name}
title={character.tracking_paused ? `${character.name} - Tracking Paused (click to resume)` : character.name}
>
{character.tracking_paused && (
<>
<span
className={clsx(
'absolute flex flex-col p-[2px] top-[0px] left-[0px] w-[35px] h-[35px]',
'text-yellow-500 text-[9px] z-10 bg-gray-800/40',
'pi',
PrimeIcons.PAUSE,
)}
/>
</>
)}
{mainCharacterEveId === character.eve_id && (
<span
className={clsx(
@@ -55,6 +75,7 @@ export const Characters = ({ data }: CharactersProps) => {
)}
/>
)}
{followingCharacterEveId === character.eve_id && (
<span
className={clsx(

View File

@@ -1,6 +1,6 @@
import React, { RefObject } from 'react';
import { ContextMenu } from 'primereact/contextmenu';
import { SolarSystemRawType } from '@/hooks/Mapper/types';
import { PingType, SolarSystemRawType } from '@/hooks/Mapper/types';
import { useContextMenuSystemItems } from '@/hooks/Mapper/components/contexts/ContextMenuSystem/useContextMenuSystemItems.tsx';
import { WaypointSetContextHandler } from '@/hooks/Mapper/components/contexts/types.ts';
@@ -19,6 +19,7 @@ export interface ContextMenuSystemProps {
onSystemStatus(val: number): void;
onSystemLabels(val: string): void;
onCustomLabelDialog(): void;
onTogglePing(type: PingType, solar_system_id: string, hasPing: boolean): void;
onWaypointSet: WaypointSetContextHandler;
}

View File

@@ -1,3 +1,4 @@
export * from './useTagMenu';
export * from './useStatusMenu';
export * from './useLabelsMenu';
export * from './useUserRoute';

View File

@@ -0,0 +1,42 @@
import { MapUserAddIcon, MapUserDeleteIcon } from '@/hooks/Mapper/icons';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useCallback, useRef } from 'react';
import { WidgetsIds } from '@/hooks/Mapper/components/mapInterface/constants.tsx';
interface UseUserRouteProps {
systemId: string | undefined;
userHubs: string[];
onUserHubToggle(): void;
}
export const useUserRoute = ({ userHubs, systemId, onUserHubToggle }: UseUserRouteProps) => {
const {
data: { isSubscriptionActive },
windowsSettings,
} = useMapRootState();
const ref = useRef({ userHubs, systemId, onUserHubToggle, isSubscriptionActive, windowsSettings });
ref.current = { userHubs, systemId, onUserHubToggle, isSubscriptionActive, windowsSettings };
return useCallback(() => {
const { userHubs, systemId, onUserHubToggle, isSubscriptionActive, windowsSettings } = ref.current;
const isVisibleUserRoutes = windowsSettings.visible.some(x => x === WidgetsIds.userRoutes);
if (!isSubscriptionActive || !isVisibleUserRoutes || !systemId) {
return [];
}
return [
{
label: !userHubs.includes(systemId) ? 'Add User Route' : 'Remove User Route',
icon: !userHubs.includes(systemId) ? (
<MapUserAddIcon className="mr-1 relative left-[-2px]" />
) : (
<MapUserDeleteIcon className="mr-1 relative left-[-2px]" />
),
command: onUserHubToggle,
},
];
}, [windowsSettings]);
};

View File

@@ -5,6 +5,7 @@ import { SolarSystemRawType } from '@/hooks/Mapper/types';
import { WaypointSetContextHandler } from '@/hooks/Mapper/components/contexts/types.ts';
import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts';
import { useDeleteSystems } from '@/hooks/Mapper/components/contexts/hooks';
// import { PingType } from '@/hooks/Mapper/types/ping.ts';
interface UseContextMenuSystemHandlersProps {
hubs: string[];
@@ -93,6 +94,22 @@ export const useContextMenuSystemHandlers = ({
setSystem(undefined);
}, []);
// const onTogglePingRally = useCallback(() => {
// const { userHubs, system, outCommand } = ref.current;
// if (!system) {
// return;
// }
//
// outCommand({
// type: OutCommand.openPing,
// data: {
// solar_system_id: system,
// type: PingType.Rally,
// },
// });
// setSystem(undefined);
// }, []);
const onSystemTag = useCallback((tag?: string) => {
const { system, outCommand } = ref.current;
if (!system) {
@@ -198,6 +215,7 @@ export const useContextMenuSystemHandlers = ({
onLockToggle,
onHubToggle,
onUserHubToggle,
// onTogglePingRally,
onSystemTag,
onSystemTemporaryName,
onSystemStatus,

View File

@@ -1,4 +1,9 @@
import { useLabelsMenu, useStatusMenu, useTagMenu } from '@/hooks/Mapper/components/contexts/ContextMenuSystem/hooks';
import {
useLabelsMenu,
useStatusMenu,
useTagMenu,
useUserRoute,
} from '@/hooks/Mapper/components/contexts/ContextMenuSystem/hooks';
import { useMemo } from 'react';
import { getSystemById } from '@/hooks/Mapper/helpers';
import classes from './ContextMenuSystem.module.scss';
@@ -10,13 +15,19 @@ import { useMapCheckPermissions } from '@/hooks/Mapper/mapRootProvider/hooks/api
import { UserPermission } from '@/hooks/Mapper/types/permissions.ts';
import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace.ts';
import { getSystemStaticInfo } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic';
import { MapAddIcon, MapDeleteIcon, MapUserAddIcon, MapUserDeleteIcon } from '@/hooks/Mapper/icons';
import { MapAddIcon, MapDeleteIcon } from '@/hooks/Mapper/icons';
import { PingType } from '@/hooks/Mapper/types';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import clsx from 'clsx';
import { MenuItem } from 'primereact/menuitem';
import { MenuItemWithInfo, WdMenuItem } from '@/hooks/Mapper/components/ui-kit';
export const useContextMenuSystemItems = ({
onDeleteSystem,
onLockToggle,
onHubToggle,
onUserHubToggle,
onTogglePing,
onSystemTag,
onSystemStatus,
onSystemLabels,
@@ -33,11 +44,33 @@ export const useContextMenuSystemItems = ({
const getLabels = useLabelsMenu(systems, systemId, onSystemLabels, onCustomLabelDialog);
const getWaypointMenu = useWaypointMenu(onWaypointSet);
const canLockSystem = useMapCheckPermissions([UserPermission.LOCK_SYSTEM]);
const canManageSystem = useMapCheckPermissions([UserPermission.UPDATE_SYSTEM]);
const canDeleteSystem = useMapCheckPermissions([UserPermission.DELETE_SYSTEM]);
const getUserRoutes = useUserRoute({ userHubs, systemId, onUserHubToggle });
return useMemo(() => {
const {
data: { pings, isSubscriptionActive },
} = useMapRootState();
const ping = useMemo(() => (pings.length === 1 ? pings[0] : undefined), [pings]);
const isShowPingBtn = useMemo(() => {
if (!isSubscriptionActive) {
return false;
}
if (pings.length === 0) {
return true;
}
return pings[0].solar_system_id === systemId;
}, [isSubscriptionActive, pings, systemId]);
return useMemo((): MenuItem[] => {
const system = systemId ? getSystemById(systems, systemId) : undefined;
const systemStaticInfo = getSystemStaticInfo(systemId)!;
const hasPing = ping?.solar_system_id === systemId;
if (!system || !systemId) {
return [];
}
@@ -72,55 +105,96 @@ export const useContextMenuSystemItems = ({
),
command: onHubToggle,
},
...getUserRoutes(),
{ separator: true },
{
label: !userHubs.includes(systemId) ? 'Add User Route' : 'Remove User Route',
icon: !userHubs.includes(systemId) ? (
<MapUserAddIcon className="mr-1 relative left-[-2px]" />
) : (
<MapUserDeleteIcon className="mr-1 relative left-[-2px]" />
),
command: onUserHubToggle,
command: () => onTogglePing(PingType.Rally, systemId, hasPing),
disabled: !isShowPingBtn,
template: () => {
const iconClasses = clsx({
'pi text-cyan-400 hero-signal': !hasPing,
'pi text-red-400 hero-signal-slash': hasPing,
});
if (isShowPingBtn) {
return <WdMenuItem icon={iconClasses}>{!hasPing ? 'Ping: RALLY' : 'Cancel: RALLY'}</WdMenuItem>;
}
return (
<MenuItemWithInfo
infoTitle="Locked. Ping can be set only for one system."
infoClass="pi-lock text-stone-500 mr-[12px]"
>
<WdMenuItem disabled icon={iconClasses}>
{!hasPing ? 'Ping: RALLY' : 'Cancel: RALLY'}
</WdMenuItem>
</MenuItemWithInfo>
);
},
},
...(system.locked
? canLockSystem
? [
{
label: 'Unlock',
icon: PrimeIcons.LOCK_OPEN,
command: onLockToggle,
},
]
: []
: [
...(canLockSystem
? [
{
label: 'Lock',
icon: PrimeIcons.LOCK,
command: onLockToggle,
},
]
: []),
...(system.locked && canLockSystem
? [
{
label: 'Unlock',
icon: PrimeIcons.LOCK_OPEN,
command: onLockToggle,
},
]
: []),
...(!system.locked && canManageSystem
? [
{
label: 'Lock',
icon: PrimeIcons.LOCK,
command: onLockToggle,
},
]
: []),
...(canDeleteSystem && !system.locked
? [
{ separator: true },
{
label: 'Delete',
icon: PrimeIcons.TRASH,
command: onDeleteSystem,
disabled: hasPing,
template: () => {
if (!hasPing) {
return <WdMenuItem icon="text-red-400 pi pi-trash">Delete</WdMenuItem>;
}
return (
<MenuItemWithInfo
infoTitle="Locked. System can not be deleted until ping set."
infoClass="pi-lock text-stone-500 mr-[12px]"
>
<WdMenuItem disabled icon="text-red-400 pi pi-trash">
Delete
</WdMenuItem>
</MenuItemWithInfo>
);
},
},
]),
]
: []),
];
}, [
canLockSystem,
systems,
systemId,
systems,
getTags,
getStatus,
getLabels,
getWaypointMenu,
getUserRoutes,
hubs,
onHubToggle,
onOpenSettings,
canLockSystem,
onLockToggle,
canDeleteSystem,
onDeleteSystem,
onOpenSettings,
onTogglePing,
ping,
isShowPingBtn,
]);
};

View File

@@ -1,5 +1,5 @@
import { useCallback, useRef } from 'react';
import { LayoutEventBlocker, WdImageSize, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
import { LayoutEventBlocker, TooltipPosition, WdImageSize, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
import { ANOIK_ICON, DOTLAN_ICON, ZKB_ICON } from '@/hooks/Mapper/icons';
import classes from './FastSystemActions.module.scss';
@@ -59,9 +59,21 @@ export const FastSystemActions = ({
return (
<LayoutEventBlocker className={clsx('flex px-2 gap-2 justify-between items-center h-full')}>
<div className={clsx('flex gap-2 items-center h-full', classes.Links)}>
<WdImgButton tooltip={{ content: 'Open zkillboard' }} source={ZKB_ICON} onClick={handleOpenZKB} />
<WdImgButton tooltip={{ content: 'Open Anoikis' }} source={ANOIK_ICON} onClick={handleOpenAnoikis} />
<WdImgButton tooltip={{ content: 'Open Dotlan' }} source={DOTLAN_ICON} onClick={handleOpenDotlan} />
<WdImgButton
tooltip={{ position: TooltipPosition.top, content: 'Open zkillboard' }}
source={ZKB_ICON}
onClick={handleOpenZKB}
/>
<WdImgButton
tooltip={{ position: TooltipPosition.top, content: 'Open Anoikis' }}
source={ANOIK_ICON}
onClick={handleOpenAnoikis}
/>
<WdImgButton
tooltip={{ position: TooltipPosition.top, content: 'Open Dotlan' }}
source={DOTLAN_ICON}
onClick={handleOpenDotlan}
/>
</div>
<div className="flex gap-2 items-center pl-1">
@@ -69,14 +81,14 @@ export const FastSystemActions = ({
textSize={WdImageSize.off}
className={PrimeIcons.COPY}
onClick={copySystemNameToClipboard}
tooltip={{ content: 'Copy system name' }}
tooltip={{ position: TooltipPosition.top, content: 'Copy system name' }}
/>
{showEdit && (
<WdImgButton
textSize={WdImageSize.off}
className="pi pi-pen-to-square text-base"
onClick={onOpenSettings}
tooltip={{ content: 'Edit system name and description' }}
tooltip={{ position: TooltipPosition.top, content: 'Edit system name and description' }}
/>
)}
</div>

View File

@@ -28,11 +28,12 @@ import {
import { getBehaviorForTheme } from './helpers/getThemeBehavior';
import { OnMapAddSystemCallback, OnMapSelectionChange } from './map.types';
import { SESSION_KEY } from '@/hooks/Mapper/constants.ts';
import { SolarSystemConnection, SolarSystemRawType } from '@/hooks/Mapper/types';
import { PingData, SolarSystemConnection, SolarSystemRawType } from '@/hooks/Mapper/types';
import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts';
import { NodeSelectionMouseHandler } from '@/hooks/Mapper/components/contexts/types.ts';
import clsx from 'clsx';
import { useBackgroundVars } from './hooks/useBackgroundVars';
import type { PanelPosition } from '@reactflow/core';
const DEFAULT_VIEW_PORT = { zoom: 1, x: 0, y: 0 };
@@ -95,6 +96,8 @@ interface MapCompProps {
isShowBackgroundPattern?: boolean;
isSoftBackground?: boolean;
theme?: string;
pings: PingData[];
minimapPlacement?: PanelPosition;
}
const MapComp = ({
@@ -112,6 +115,8 @@ const MapComp = ({
isSoftBackground,
theme,
onAddSystem,
pings,
minimapPlacement = 'bottom-right',
}: MapCompProps) => {
const { getNodes } = useReactFlow();
const [nodes, , onNodesChange] = useNodesState<Node<SolarSystemRawType>>(initialNodes);
@@ -206,8 +211,9 @@ const MapComp = ({
...x,
showKSpaceBG: showKSpaceBG,
isThickConnections: isThickConnections,
pings,
}));
}, [showKSpaceBG, isThickConnections, update]);
}, [showKSpaceBG, isThickConnections, pings, update]);
return (
<>
@@ -270,7 +276,9 @@ const MapComp = ({
// onlyRenderVisibleElements
selectionMode={SelectionMode.Partial}
>
{isShowMinimap && <MiniMap pannable zoomable ariaLabel="Mini map" className={minimapClasses} />}
{isShowMinimap && (
<MiniMap pannable zoomable ariaLabel="Mini map" className={minimapClasses} position={minimapPlacement} />
)}
{isShowBackgroundPattern && <Background variant={variant} gap={gap} size={size} color={color} />}
</ReactFlow>
{/* <button className="z-auto btn btn-primary absolute top-20 right-20" onClick={handleGetPassages}>

View File

@@ -40,6 +40,8 @@ const INITIAL_DATA: MapData = {
isSubscriptionActive: false,
mainCharacterEveId: null,
followingCharacterEveId: null,
userHubs: [],
pings: [],
};
export interface MapContextProps {

View File

@@ -1,11 +1,23 @@
@import '@/hooks/Mapper/components/map/styles/eve-common-variables';
$pastel-blue: #5a7d9a;
$pastel-pink: #d291bc;
$pastel-pink: rgb(30, 161, 255);
$dark-bg: #2d2d2d;
$text-color: #ffffff;
$tooltip-bg: #202020;
$neon-color-1: rgb(27, 132, 236);
$neon-color-3: rgba(27, 132, 236, 0.40);
@keyframes move-stripes {
from {
background-position: 0 0;
}
to {
background-position: 30px 0;
}
}
.RootCustomNode {
display: flex;
width: 130px;
@@ -32,7 +44,7 @@ $tooltip-bg: #202020;
&.Amarria,
&.Gallente,
&.Caldaria {
&::before {
&::after {
content: '';
position: absolute;
top: 0;
@@ -48,7 +60,7 @@ $tooltip-bg: #202020;
}
&.Mataria {
&::before {
&::after {
background-image: url('/images/mataria-180.png');
opacity: 0.6;
background-position-x: 1px;
@@ -57,7 +69,7 @@ $tooltip-bg: #202020;
}
&.Caldaria {
&::before {
&::after {
background-image: url('/images/caldaria-180.png');
opacity: 0.6;
background-position-x: 1px;
@@ -66,7 +78,7 @@ $tooltip-bg: #202020;
}
&.Amarria {
&::before {
&::after {
opacity: 0.45;
background-image: url('/images/amarr-180.png');
background-position-x: 0;
@@ -75,7 +87,7 @@ $tooltip-bg: #202020;
}
&.Gallente {
&::before {
&::after {
opacity: 0.5;
background-image: url('/images/gallente-180.png');
background-position-x: 1px;
@@ -88,6 +100,29 @@ $tooltip-bg: #202020;
box-shadow: 0 0 10px #9a1af1c2;
}
&.rally {
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
border-color: $neon-color-1;
background: repeating-linear-gradient(
45deg,
$neon-color-3 0px,
$neon-color-3 8px,
transparent 8px,
transparent 21px
);
background-size: 30px 30px;
animation: move-stripes 3s linear infinite;
}
}
&.eve-system-status-home {
border: 1px solid var(--eve-solar-system-status-color-home-dark30);
background-image: linear-gradient(45deg, var(--eve-solar-system-status-color-background), transparent);

View File

@@ -71,8 +71,11 @@ export const SolarSystemNodeDefault = memo((props: NodeProps<MapSolarSystemType>
className={clsx(
classes.RootCustomNode,
nodeVars.regionClass && classes[nodeVars.regionClass],
nodeVars.status !== undefined ? classes[STATUS_CLASSES[nodeVars.status]] : '',
{ [classes.selected]: nodeVars.selected },
nodeVars.status !== undefined && classes[STATUS_CLASSES[nodeVars.status]],
{
[classes.selected]: nodeVars.selected,
[classes.rally]: nodeVars.isRally,
},
)}
onMouseDownCapture={e => nodeVars.dbClick(e)}
>

View File

@@ -71,7 +71,10 @@ export const SolarSystemNodeTheme = memo((props: NodeProps<MapSolarSystemType>)
classes.RootCustomNode,
nodeVars.regionClass && classes[nodeVars.regionClass],
nodeVars.status !== undefined ? classes[STATUS_CLASSES[nodeVars.status]] : '',
{ [classes.selected]: nodeVars.selected },
{
[classes.selected]: nodeVars.selected,
[classes.rally]: nodeVars.isRally,
},
)}
onMouseDownCapture={e => nodeVars.dbClick(e)}
>
@@ -116,23 +119,13 @@ export const SolarSystemNodeTheme = memo((props: NodeProps<MapSolarSystemType>)
<div className={clsx(classes.BottomRow, 'flex items-center justify-between')}>
{nodeVars.customName && (
<div
className={clsx(
classes.CustomName,
'[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)] whitespace-nowrap overflow-hidden text-ellipsis mr-0.5',
)}
>
<div className="[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)] whitespace-nowrap overflow-hidden text-ellipsis mr-0.5">
{nodeVars.customName}
</div>
)}
{!nodeVars.isWormhole && !nodeVars.customName && (
<div
className={clsx(
classes.RegionName,
'[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)] whitespace-nowrap overflow-hidden text-ellipsis mr-0.5',
)}
>
<div className="[text-shadow:_0_1px_0_rgb(0_0_0_/_40%)] whitespace-nowrap overflow-hidden text-ellipsis mr-0.5">
{nodeVars.regionName}
</div>
)}

View File

@@ -1,5 +1,4 @@
import { useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
import { useCallback, useRef } from 'react';
import {
CommandCharacterAdded,
CommandCharacterRemoved,
@@ -7,6 +6,7 @@ import {
CommandCharacterUpdated,
CommandPresentCharacters,
} from '@/hooks/Mapper/types';
import { useCallback, useRef } from 'react';
export const useCommandsCharacters = () => {
const { update } = useMapState();

View File

@@ -1,8 +1,8 @@
import { useReactFlow } from 'reactflow';
import { useCallback, useRef } from 'react';
import { CommandInit } from '@/hooks/Mapper/types/mapHandlers.ts';
import { convertConnection2Edge, convertSystem2Node } from '../../helpers';
import { MapData, useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
import { CommandInit } from '@/hooks/Mapper/types/mapHandlers.ts';
import { useCallback, useRef } from 'react';
import { useReactFlow } from 'reactflow';
import { convertConnection2Edge, convertSystem2Node } from '../../helpers';
export const useMapInit = () => {
const rf = useReactFlow();

View File

@@ -115,35 +115,18 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
}, 500);
break;
case Commands.pingAdded:
case Commands.pingCancelled:
case Commands.routes:
// do nothing here
break;
case Commands.signaturesUpdated:
// do nothing here
break;
case Commands.linkSignatureToSystem:
// do nothing here
break;
case Commands.detailedKillsUpdated:
// do nothing here
break;
case Commands.characterActivityData:
break;
case Commands.trackingCharactersData:
break;
case Commands.updateActivity:
break;
case Commands.updateTracking:
break;
case Commands.userSettingsUpdated:
// do nothing
break;
default:

View File

@@ -9,7 +9,7 @@ import { REGIONS_MAP, Spaces } from '@/hooks/Mapper/constants';
import { isWormholeSpace } from '@/hooks/Mapper/components/map/helpers/isWormholeSpace';
import { getSystemClassStyles } from '@/hooks/Mapper/components/map/helpers';
import { sortWHClasses } from '@/hooks/Mapper/helpers';
import { CharacterTypeRaw, OutCommand, SystemSignature } from '@/hooks/Mapper/types';
import { CharacterTypeRaw, OutCommand, PingType, SystemSignature } from '@/hooks/Mapper/types';
import { useUnsplashedSignatures } from './useUnsplashedSignatures';
import { useSystemName } from './useSystemName';
import { LabelInfo, useLabelsInfo } from './useLabelsInfo';
@@ -21,6 +21,45 @@ function getActivityType(count: number): string {
return 'activityDanger';
}
export interface SolarSystemNodeVars {
id: string;
selected: boolean;
visible: boolean;
isWormhole: boolean;
classTitleColor: string | null;
killsCount: number | null;
killsActivityType: string | null;
hasUserCharacters: boolean;
showHandlers: boolean;
regionClass: string | null;
systemName: string;
customName?: string | null;
labelCustom: string | null;
isShattered: boolean;
tag?: string | null;
status?: number;
labelsInfo: LabelInfo[];
dbClick: (event: React.MouseEvent<HTMLDivElement>) => void;
sortedStatics: Array<string | number>;
effectName: string | null;
regionName: string | null;
solarSystemId: string;
solarSystemName: string | null;
locked: boolean;
hubs: string[];
name: string | null;
isConnecting: boolean;
hoverNodeId: string | null;
charactersInSystem: Array<CharacterTypeRaw>;
userCharacters: string[];
unsplashedLeft: Array<SystemSignature>;
unsplashedRight: Array<SystemSignature>;
isThickConnections: boolean;
isRally: boolean;
classTitle: string | null;
temporaryName?: string | null;
}
const SpaceToClass: Record<string, string> = {
[Spaces.Caldari]: 'Caldaria',
[Spaces.Matar]: 'Mataria',
@@ -41,7 +80,7 @@ export function useLocalCounter(nodeVars: SolarSystemNodeVars) {
return { localCounterCharacters };
}
export function useSolarSystemNode(props: NodeProps<MapSolarSystemType>): SolarSystemNodeVars {
export const useSolarSystemNode = (props: NodeProps<MapSolarSystemType>): SolarSystemNodeVars => {
const { id, data, selected } = props;
const {
id: solar_system_id,
@@ -92,6 +131,7 @@ export function useSolarSystemNode(props: NodeProps<MapSolarSystemType>): SolarS
visibleNodes,
showKSpaceBG,
isThickConnections,
pings,
},
outCommand,
} = useMapState();
@@ -154,6 +194,11 @@ export function useSolarSystemNode(props: NodeProps<MapSolarSystemType>): SolarS
const hubsAsStrings = useMemo(() => hubs.map(item => item.toString()), [hubs]);
const isRally = useMemo(
() => pings.find(x => x.solar_system_id === solar_system_id && x.type === PingType.Rally),
[pings, solar_system_id],
);
const nodeVars: SolarSystemNodeVars = {
id,
selected,
@@ -190,45 +235,8 @@ export function useSolarSystemNode(props: NodeProps<MapSolarSystemType>): SolarS
temporaryName: computedTemporaryName,
regionName: region_name,
solarSystemName: solar_system_name,
isRally,
};
return nodeVars;
}
export interface SolarSystemNodeVars {
id: string;
selected: boolean;
visible: boolean;
isWormhole: boolean;
classTitleColor: string | null;
killsCount: number | null;
killsActivityType: string | null;
hasUserCharacters: boolean;
showHandlers: boolean;
regionClass: string | null;
systemName: string;
customName?: string | null;
labelCustom: string | null;
isShattered: boolean;
tag?: string | null;
status?: number;
labelsInfo: LabelInfo[];
dbClick: (event: React.MouseEvent<HTMLDivElement>) => void;
sortedStatics: Array<string | number>;
effectName: string | null;
regionName: string | null;
solarSystemId: string;
solarSystemName: string | null;
locked: boolean;
hubs: string[];
name: string | null;
isConnecting: boolean;
hoverNodeId: string | null;
charactersInSystem: Array<CharacterTypeRaw>;
userCharacters: string[];
unsplashedLeft: Array<SystemSignature>;
unsplashedRight: Array<SystemSignature>;
isThickConnections: boolean;
classTitle: string | null;
temporaryName?: string | null;
}
};

View File

@@ -1,9 +1,12 @@
import classes from './MarkdownComment.module.scss';
import clsx from 'clsx';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { InfoDrawer, TimeAgo, TooltipPosition, WdImgButton } from '@/hooks/Mapper/components/ui-kit';
import remarkBreaks from 'remark-breaks';
import {
InfoDrawer,
MarkdownTextViewer,
TimeAgo,
TooltipPosition,
WdImgButton,
} from '@/hooks/Mapper/components/ui-kit';
import { useGetCacheCharacter } from '@/hooks/Mapper/mapRootProvider/hooks/api';
import { useCallback, useRef, useState } from 'react';
import { WdTransition } from '@/hooks/Mapper/components/ui-kit/WdTransition/WdTransition.tsx';
@@ -13,7 +16,6 @@ import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { OutCommand } from '@/hooks/Mapper/types';
const TOOLTIP_PROPS = { content: 'Remove comment', position: TooltipPosition.top };
const REMARK_PLUGINS = [remarkGfm, remarkBreaks];
export interface MarkdownCommentProps {
text: string;
@@ -79,7 +81,7 @@ export const MarkdownComment = ({ text, time, characterEveId, id }: MarkdownComm
</div>
}
>
<Markdown remarkPlugins={REMARK_PLUGINS}>{text}</Markdown>
<MarkdownTextViewer>{text}</MarkdownTextViewer>
</InfoDrawer>
<ConfirmPopup

View File

@@ -9,6 +9,7 @@ import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
export interface CommentsEditorProps {}
// eslint-disable-next-line no-empty-pattern
export const CommentsEditor = ({}: CommentsEditorProps) => {
const [textVal, setTextVal] = useState('');

View File

@@ -0,0 +1,49 @@
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useMemo } from 'react';
import { RoutesList } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesList';
export const PingRoute = () => {
const {
data: { routes, pings, loadingPublicRoutes },
} = useMapRootState();
const route = useMemo(() => {
const [ping] = pings;
if (!ping) {
return null;
}
return routes?.routes.find(x => ping.solar_system_id === x.destination.toString()) ?? null;
}, [routes, pings]);
const preparedRoute = useMemo(() => {
if (!route) {
return null;
}
return {
...route,
mapped_systems:
route.systems?.map(solar_system_id =>
routes?.systems_static_data.find(
system_static_data => system_static_data.solar_system_id === solar_system_id,
),
) ?? [],
};
}, [route, routes?.systems_static_data]);
if (loadingPublicRoutes) {
return <span className="m-0 text-[12px]">Loading...</span>;
}
if (!preparedRoute || preparedRoute.origin === preparedRoute.destination) {
return null;
}
return (
<div className="m-0 flex gap-2 items-center text-[12px]">
{preparedRoute.has_connection && <div className="text-[12px]">{preparedRoute.systems?.length ?? 2}</div>}
<RoutesList data={preparedRoute} />
</div>
);
};

View File

@@ -0,0 +1,284 @@
import { Button } from 'primereact/button';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Toast } from 'primereact/toast';
import clsx from 'clsx';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { Commands, OutCommand, PingType } from '@/hooks/Mapper/types';
import {
CharacterCardById,
SystemView,
TimeAgo,
TooltipPosition,
WdImgButton,
WdImgButtonTooltip,
} from '@/hooks/Mapper/components/ui-kit';
import useRefState from 'react-usestateref';
import { PrimeIcons } from 'primereact/api';
import { emitMapEvent } from '@/hooks/Mapper/events';
import { ConfirmPopup } from 'primereact/confirmpopup';
import { PingRoute } from '@/hooks/Mapper/components/mapInterface/components/PingsInterface/PingRoute.tsx';
import { PingsPlacement } from '@/hooks/Mapper/mapRootProvider/types.ts';
const PING_PLACEMENT_MAP = {
[PingsPlacement.rightTop]: 'top-right',
[PingsPlacement.leftTop]: 'top-left',
[PingsPlacement.rightBottom]: 'bottom-right',
[PingsPlacement.leftBottom]: 'bottom-left',
};
const PING_PLACEMENT_MAP_OFFSETS = {
[PingsPlacement.rightTop]: { default: '!top-[56px]', withLeftMenu: '!top-[56px] !right-[64px]' },
[PingsPlacement.rightBottom]: { default: '!bottom-[15px]', withLeftMenu: '!bottom-[15px] !right-[64px]' },
[PingsPlacement.leftTop]: { default: '!top-[56px] !left-[64px]', withLeftMenu: '!top-[56px] !left-[64px]' },
[PingsPlacement.leftBottom]: { default: '!left-[64px] !bottom-[15px]', withLeftMenu: '!bottom-[15px]' },
};
const CLOSE_TOOLTIP_PROPS: WdImgButtonTooltip = {
content: 'Hide',
position: TooltipPosition.top,
className: '!leading-[0]',
};
const NAVIGATE_TOOLTIP_PROPS: WdImgButtonTooltip = {
content: 'Navigate To',
position: TooltipPosition.top,
className: '!leading-[0]',
};
const DELETE_TOOLTIP_PROPS: WdImgButtonTooltip = {
content: 'Remove',
position: TooltipPosition.top,
className: '!leading-[0]',
};
// const TOOLTIP_WAYPOINT_PROPS: WdImgButtonTooltip = {
// content: 'Waypoint',
// position: TooltipPosition.bottom,
// className: '!leading-[0]',
// };
const TITLES = {
[PingType.Alert]: 'Alert',
[PingType.Rally]: 'Rally Point',
};
const ICONS = {
[PingType.Alert]: 'pi-bell',
[PingType.Rally]: 'pi-bell',
};
export interface PingsInterfaceProps {
hasLeftOffset?: boolean;
}
// TODO: right now can be one ping. But in future will be multiple pings then:
// 1. we will use this as container
// 2. we will create PingInstance (which will contains ping Button and Toast
// 3. ADD Context menu
export const PingsInterface = ({ hasLeftOffset }: PingsInterfaceProps) => {
const toast = useRef<Toast>(null);
const [isShow, setIsShow, isShowRef] = useRefState(false);
const cpRemoveBtnRef = useRef<HTMLElement>();
const [cpRemoveVisible, setCpRemoveVisible] = useState(false);
const {
storedSettings: { interfaceSettings },
data: { pings, selectedSystems },
outCommand,
} = useMapRootState();
const selectedSystem = useMemo(() => {
if (selectedSystems.length !== 1) {
return null;
}
return selectedSystems[0];
}, [selectedSystems]);
const ping = useMemo(() => (pings.length === 1 ? pings[0] : null), [pings]);
const handleShowCP = useCallback(() => setCpRemoveVisible(true), []);
const handleHideCP = useCallback(() => setCpRemoveVisible(false), []);
const navigateTo = useCallback(() => {
if (!ping) {
return;
}
emitMapEvent({
name: Commands.centerSystem,
data: ping.solar_system_id?.toString(),
});
}, [ping]);
const removePing = useCallback(async () => {
if (!ping) {
return;
}
await outCommand({
type: OutCommand.cancelPing,
data: { type: ping.type, solar_system_id: ping.solar_system_id },
});
}, [outCommand, ping]);
useEffect(() => {
if (!ping) {
return;
}
const tid = setTimeout(() => {
toast.current?.replace({ severity: 'warn', detail: ping.message });
setIsShow(true);
}, 200);
return () => clearTimeout(tid);
}, [ping]);
const handleClickShow = useCallback(() => {
if (!ping) {
return;
}
if (!isShowRef.current) {
toast.current?.show({ severity: 'warn', detail: ping.message });
setIsShow(true);
return;
}
toast.current?.clear();
setIsShow(false);
}, [ping]);
const handleClickHide = useCallback(() => {
toast.current?.clear();
setIsShow(false);
}, []);
const { placement, offsets } = useMemo(() => {
const rawPlacement =
interfaceSettings.pingsPlacement == null ? PingsPlacement.rightTop : interfaceSettings.pingsPlacement;
return {
placement: PING_PLACEMENT_MAP[rawPlacement],
offsets: PING_PLACEMENT_MAP_OFFSETS[rawPlacement],
};
}, [interfaceSettings]);
if (!ping) {
return null;
}
const isShowSelectedSystem = selectedSystem != null && selectedSystem !== ping.solar_system_id;
return (
<>
<Toast
position={placement as never}
className={clsx('!max-w-[initial] w-[500px]', hasLeftOffset ? offsets.withLeftMenu : offsets.default)}
ref={toast}
content={({ message }) => (
<section
className={clsx(
'flex flex-col p-3 w-full border border-stone-800 shadow-md animate-fadeInDown rounded-[5px]',
'bg-gradient-to-tr from-transparent to-sky-700/60 bg-stone-900/70',
)}
>
<div className="flex gap-3">
<i className={clsx('pi text-yellow-500 text-2xl', 'relative top-[2px]', ICONS[ping.type])}></i>
<div className="flex flex-col gap-1 w-full">
<div className="flex justify-between">
<div>
<div className="m-0 font-semibold text-base text-white">{TITLES[ping.type]}</div>
<div className="flex gap-1 items-center">
{isShowSelectedSystem && (
<>
<SystemView systemId={selectedSystem} />
<span className="pi pi-angle-double-right text-[10px] relative top-[1px] text-stone-400" />
</>
)}
<SystemView systemId={ping.solar_system_id} />
{isShowSelectedSystem && (
<WdImgButton
className={clsx(PrimeIcons.QUESTION_CIRCLE, 'ml-[2px] relative top-[-2px] !text-[10px]')}
tooltip={{
position: TooltipPosition.top,
content: (
<div className="flex flex-col gap-1">
The settings for the route are taken from the Routes settings and can be configured
through them.
</div>
),
}}
/>
)}
</div>
</div>
<div className="flex flex-col items-end">
<CharacterCardById className="" characterId={ping.character_eve_id} simpleMode />
<TimeAgo timestamp={ping.inserted_at.toString()} className="text-stone-400 text-[11px]" />
</div>
</div>
{selectedSystem != null && <PingRoute />}
<p className="m-0 text-[13px] text-stone-200 min-h-[20px] pr-[16px]">{message.detail}</p>
</div>
<WdImgButton
className={clsx(PrimeIcons.TIMES, 'hover:text-red-400 mt-[3px]')}
tooltip={CLOSE_TOOLTIP_PROPS}
onClick={handleClickHide}
/>
</div>
{/*Button bar*/}
<div className="flex justify-end items-center gap-2 h-0 relative top-[-8px]">
<WdImgButton
className={clsx('pi-compass', 'hover:text-red-400 mt-[3px]')}
tooltip={NAVIGATE_TOOLTIP_PROPS}
onClick={navigateTo}
/>
{/*@ts-ignore*/}
<div ref={cpRemoveBtnRef}>
<WdImgButton
className={clsx('pi-trash', 'text-red-400 hover:text-red-300')}
tooltip={DELETE_TOOLTIP_PROPS}
onClick={handleShowCP}
/>
</div>
{/* TODO ADD solar system menu*/}
{/*<WdImgButton*/}
{/* className={clsx('pi-map-marker', 'hover:text-red-400 mt-[3px]')}*/}
{/* tooltip={TOOLTIP_WAYPOINT_PROPS}*/}
{/* onClick={handleClickHide}*/}
{/*/>*/}
</div>
</section>
)}
></Toast>
<Button
icon="pi pi-bell"
severity="warning"
aria-label="Notification"
size="small"
className="w-[33px] h-[33px]"
outlined
onClick={handleClickShow}
disabled={isShow}
/>
<ConfirmPopup
target={cpRemoveBtnRef.current}
visible={cpRemoveVisible}
onHide={handleHideCP}
message="Are you sure you want to delete ping?"
icon="pi pi-exclamation-triangle text-orange-400"
accept={removePing}
/>
</>
);
};

View File

@@ -0,0 +1 @@
export * from './PingsInterface.tsx';

View File

@@ -146,7 +146,7 @@ export const SystemLinkSignatureDialog = ({ data, setVisible }: SystemLinkSignat
}
const whShipSize = getWhSize(wormholes, signature.type);
if (whShipSize) {
if (whShipSize !== undefined && whShipSize !== null) {
await outCommand({
type: OutCommand.updateConnectionShipSizeType,
data: {

View File

@@ -0,0 +1,101 @@
import { InputTextarea } from 'primereact/inputtextarea';
import { Dialog } from 'primereact/dialog';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useCallback, useRef, useState } from 'react';
import { Button } from 'primereact/button';
import { OutCommand } from '@/hooks/Mapper/types';
import { PingType } from '@/hooks/Mapper/types/ping.ts';
import { SystemView } from '@/hooks/Mapper/components/ui-kit';
import clsx from 'clsx';
const PING_TITLES = {
[PingType.Rally]: 'RALLY',
[PingType.Alert]: 'ALERT',
};
interface SystemPingDialogProps {
systemId: string;
type: PingType;
visible: boolean;
setVisible: (visible: boolean) => void;
}
export const SystemPingDialog = ({ systemId, type, visible, setVisible }: SystemPingDialogProps) => {
const { outCommand } = useMapRootState();
const [message, setMessage] = useState('');
const inputRef = useRef<HTMLTextAreaElement>();
const ref = useRef({ message, outCommand, systemId, type });
ref.current = { message, outCommand, systemId, type };
const handleSave = useCallback(() => {
const { message, outCommand, systemId, type } = ref.current;
outCommand({
type: OutCommand.addPing,
data: {
solar_system_id: systemId,
type,
message,
},
});
setVisible(false);
}, [setVisible]);
const onShow = useCallback(() => {
inputRef.current?.focus();
}, []);
return (
<Dialog
header={
<div className="flex gap-1 text-[13px] items-center text-stone-300">
<div>Ping:{` `}</div>
<div
className={clsx({
['text-cyan-400']: type === PingType.Rally,
})}
>
{PING_TITLES[type]}
</div>
<div className="text-[11px]">in</div> <SystemView systemId={systemId} className="relative top-[1px]" />
</div>
}
visible={visible}
draggable={false}
style={{ width: '450px' }}
onShow={onShow}
onHide={() => {
if (!visible) {
return;
}
setVisible(false);
}}
>
<form onSubmit={handleSave}>
<div className="flex flex-col gap-3 px-2">
<div className="flex flex-col gap-1">
<label className="text-[11px]" htmlFor="username">
Message
</label>
<InputTextarea
// @ts-ignore
ref={inputRef}
autoResize
rows={3}
cols={30}
value={message}
onChange={e => setMessage(e.target.value)}
/>
</div>
<div className="flex gap-2 justify-end">
<Button onClick={handleSave} size="small" severity="danger" label="Ping!"></Button>
</div>
</div>
</form>
</Dialog>
);
};

View File

@@ -0,0 +1 @@
export * from './SystemPingDialog';

View File

@@ -2,3 +2,4 @@ export * from './Widget';
export * from './SystemSettingsDialog';
export * from './SystemCustomLabelDialog';
export * from './SystemLinkSignatureDialog';
export * from './PingsInterface';

View File

@@ -62,7 +62,7 @@ export const DEFAULT_WIDGETS: WindowProps[] = [
},
{
id: WidgetsIds.userRoutes,
position: { x: 10, y: 530 },
position: { x: 10, y: 10 },
size: { width: 510, height: 200 },
zIndex: 0,
content: () => <WRoutesUser />,

View File

@@ -1,6 +1,10 @@
import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types';
export const sortCharacters = (a: CharacterTypeRaw & WithIsOwnCharacter, b: CharacterTypeRaw & WithIsOwnCharacter) => {
if (a.online === b.online) {
return a.name.localeCompare(b.name);
}
if (a.online !== b.online) {
return a.online && !b.online ? -1 : 1;
}

View File

@@ -1,8 +1,8 @@
import classes from './LocalCharactersItemTemplate.module.scss';
import clsx from 'clsx';
import { CharacterCard } from '@/hooks/Mapper/components/ui-kit';
import { CharItemProps } from '@/hooks/Mapper/components/mapInterface/widgets/LocalCharacters/components';
import { CharacterCard } from '@/hooks/Mapper/components/ui-kit';
import clsx from 'clsx';
import { VirtualScrollerTemplateOptions } from 'primereact/virtualscroller';
import classes from './LocalCharactersItemTemplate.module.scss';
export type LocalCharactersItemTemplateProps = { showShipName: boolean } & CharItemProps &
VirtualScrollerTemplateOptions;
@@ -22,7 +22,7 @@ export const LocalCharactersItemTemplate = ({ showShipName, ...options }: LocalC
)}
style={{ height: `${options.props.itemSize}px` }}
>
<CharacterCard showShipName={showShipName} showTicker {...options} />
<CharacterCard showShipName={showShipName} showTicker showShip {...options} />
</div>
);
};

View File

@@ -1,4 +1,4 @@
import React, { createContext, forwardRef, useContext, useImperativeHandle, useState } from 'react';
import React, { createContext, forwardRef, useContext } from 'react';
import {
RoutesImperativeHandle,
RoutesProviderInnerProps,
@@ -15,17 +15,14 @@ const RoutesContext = createContext<RoutesProviderInnerProps>({
data: {},
});
export const RoutesProvider = forwardRef<RoutesImperativeHandle, MapProviderProps>(({ children, ...props }, ref) => {
const [loading, setLoading] = useState(false);
// INFO: this component have imperative handler but now it not using.
export const RoutesProvider = forwardRef<RoutesImperativeHandle, MapProviderProps>(
({ children, ...props } /*, ref*/) => {
// useImperativeHandle(ref, () => ({}));
useImperativeHandle(ref, () => ({
stopLoading() {
setLoading(false);
},
}));
return <RoutesContext.Provider value={{ ...props, loading, setLoading }}>{children}</RoutesContext.Provider>;
});
return <RoutesContext.Provider value={{ ...props /*, loading, setLoading*/ }}>{children}</RoutesContext.Provider>;
},
);
RoutesProvider.displayName = 'RoutesProvider';
export const useRouteProvider = () => {

View File

@@ -3,16 +3,15 @@ import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import {
LayoutEventBlocker,
LoadingWrapper,
SystemViewStandalone,
SystemView,
TooltipPosition,
WdCheckbox,
WdImgButton,
} from '@/hooks/Mapper/components/ui-kit';
import { useLoadSystemStatic } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
import { forwardRef, MouseEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { getSystemById } from '@/hooks/Mapper/helpers/getSystemById.ts';
import classes from './RoutesWidget.module.scss';
import { useLoadRoutes } from './hooks';
import { RoutesList } from './RoutesList';
import clsx from 'clsx';
import { Route } from '@/hooks/Mapper/types/routes.ts';
@@ -42,24 +41,13 @@ export const RoutesWidgetContent = () => {
const {
data: { selectedSystems, systems, isSubscriptionActive },
} = useMapRootState();
const { hubs = [], routesList, isRestricted } = useRouteProvider();
const { hubs = [], routesList, isRestricted, loading } = useRouteProvider();
const [systemId] = selectedSystems;
const { loading } = useLoadRoutes();
const { systems: systemStatics, loadSystems, lastUpdateKey } = useLoadSystemStatic({ systems: hubs ?? [] });
const { systems: systemStatics, loadSystems } = useLoadSystemStatic({ systems: hubs ?? [] });
const { open, ...systemCtxProps } = useContextMenuSystemInfoHandlers();
const preparedHubs = useMemo(() => {
return hubs.map(x => {
const sys = getSystemById(systems, x.toString());
return { ...systemStatics.get(parseInt(x))!, ...(sys && { customName: sys.name ?? '' }) };
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hubs, systems, systemStatics, lastUpdateKey]);
const preparedRoutes: Route[] = useMemo(() => {
return (
routesList?.routes
@@ -125,9 +113,7 @@ export const RoutesWidgetContent = () => {
<LoadingWrapper loading={loading}>
<div className={clsx(classes.RoutesGrid, 'px-2 py-2')}>
{preparedRoutes.map(route => {
const sys = preparedHubs.find(x => x.solar_system_id === route.destination)!;
// TODO do not delte this console log
// TODO do not delete this console log
// eslint-disable-next-line no-console
// console.log('JOipP', `Check sys [${route.destination}]:`, sys);
@@ -144,12 +130,12 @@ export const RoutesWidgetContent = () => {
}}
/>
<SystemViewStandalone
key={route.destination}
<SystemView
systemId={route.destination.toString()}
className={clsx('select-none text-center cursor-context-menu')}
hideRegion
compact
{...sys}
showCustomName
/>
</div>
<div className="text-right pl-1">{route.has_connection ? route.systems?.length ?? 2 : ''}</div>

View File

@@ -1,7 +1,8 @@
import { useCallback, useEffect, useRef } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useRouteProvider } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesProvider.tsx';
import { RoutesType } from '@/hooks/Mapper/mapRootProvider/types.ts';
import { LoadRoutesCommand } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/types.ts';
import { RoutesList } from '@/hooks/Mapper/types/routes.ts';
function usePrevious<T>(value: T): T | undefined {
const ref = useRef<T>();
@@ -13,8 +14,22 @@ function usePrevious<T>(value: T): T | undefined {
return ref.current;
}
export const useLoadRoutes = () => {
const { data: routesSettings, loadRoutesCommand, hubs, routesList, loading, setLoading } = useRouteProvider();
type UseLoadRoutesProps = {
loadRoutesCommand: LoadRoutesCommand;
hubs: string[];
routesList: RoutesList | undefined;
data: RoutesType;
deps?: unknown[];
};
export const useLoadRoutes = ({
data: routesSettings,
loadRoutesCommand,
hubs,
routesList,
deps = [],
}: UseLoadRoutesProps) => {
const [loading, setLoading] = useState(false);
const {
data: { selectedSystems, systems, connections },
@@ -55,7 +70,8 @@ export const useLoadRoutes = () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
.map(x => routesSettings[x]),
...deps,
]);
return { loading, loadRoutes };
return { loading, loadRoutes, setLoading };
};

View File

@@ -10,17 +10,14 @@ export type RoutesWidgetProps = {
update: (d: RoutesType) => void;
hubs: string[];
routesList: RoutesList | undefined;
loading: boolean;
loadRoutesCommand: LoadRoutesCommand;
addHubCommand: AddHubCommand;
toggleHubCommand: ToggleHubCommand;
isRestricted?: boolean;
};
export type RoutesProviderInnerProps = RoutesWidgetProps & {
loading: boolean;
setLoading(loading: boolean): void;
};
export type RoutesProviderInnerProps = RoutesWidgetProps;
export type RoutesImperativeHandle = {
stopLoading: () => void;

View File

@@ -10,7 +10,7 @@ export interface SignatureViewProps {
export const SignatureView = ({ signature, showCharacterPortrait = false }: SignatureViewProps) => {
const isWormhole = signature?.group === SignatureGroup.Wormhole;
const hasCharacterInfo = showCharacterPortrait && signature.character_eve_id;
const groupDisplay = isWormhole ? SignatureGroup.Wormhole : (signature?.group ?? SignatureGroup.CosmicSignature);
const groupDisplay = isWormhole ? SignatureGroup.Wormhole : signature?.group ?? SignatureGroup.CosmicSignature;
const characterName = signature.character_name || 'Unknown character';
return (

View File

@@ -19,7 +19,7 @@ export type HeaderProps = {
lazyDeleteValue: boolean;
onLazyDeleteChange: (checked: boolean) => void;
pendingCount: number;
pendingTimeRemaining?: number; // Time remaining in ms
undoCountdown?: number;
onUndoClick: () => void;
onSettingsClick: () => void;
};
@@ -29,7 +29,7 @@ export const SystemSignaturesHeader = ({
lazyDeleteValue,
onLazyDeleteChange,
pendingCount,
pendingTimeRemaining,
undoCountdown,
onUndoClick,
onSettingsClick,
}: HeaderProps) => {
@@ -43,13 +43,6 @@ export const SystemSignaturesHeader = ({
const containerRef = useRef<HTMLDivElement>(null);
const isCompact = useMaxWidth(containerRef, COMPACT_MAX_WIDTH);
// Format time remaining as seconds
const formatTimeRemaining = () => {
if (!pendingTimeRemaining) return '';
const seconds = Math.ceil(pendingTimeRemaining / 1000);
return ` (${seconds}s remaining)`;
};
return (
<div ref={containerRef} className="w-full">
<div className="flex justify-between items-center text-xs w-full h-full">
@@ -78,7 +71,9 @@ export const SystemSignaturesHeader = ({
<WdImgButton
className={PrimeIcons.UNDO}
style={{ color: 'red' }}
tooltip={{ content: `Undo pending changes (${pendingCount})${formatTimeRemaining()}` }}
tooltip={{
content: `Undo pending deletions (${pendingCount})${undoCountdown && undoCountdown > 0 ? `${undoCountdown}s left` : ''}`,
}}
onClick={onUndoClick}
/>
)}

View File

@@ -1,99 +1,179 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useState, useEffect, useRef, useMemo } from 'react';
import { Widget } from '@/hooks/Mapper/components/mapInterface/components';
import { SystemSignaturesContent } from './SystemSignaturesContent';
import { SystemSignatureSettingsDialog } from './SystemSignatureSettingsDialog';
import { ExtendedSystemSignature, SystemSignature } from '@/hooks/Mapper/types';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useHotkey } from '@/hooks/Mapper/hooks';
import { SystemSignaturesHeader } from './SystemSignatureHeader';
import useLocalStorageState from 'use-local-storage-state';
import { useHotkey } from '@/hooks/Mapper/hooks/useHotkey';
import {
SETTINGS_KEYS,
SETTINGS_VALUES,
SIGNATURE_DELETION_TIMEOUTS,
SIGNATURE_SETTING_STORE_KEY,
SIGNATURE_WINDOW_ID,
SIGNATURES_DELETION_TIMING,
SignatureSettingsType,
getDeletionTimeoutMs,
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
import { calculateTimeRemaining } from './helpers';
import { OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers';
import { ExtendedSystemSignature } from '@/hooks/Mapper/types';
export const SystemSignatures = () => {
const [visible, setVisible] = useState(false);
const [sigCount, setSigCount] = useState<number>(0);
const [pendingSigs, setPendingSigs] = useState<SystemSignature[]>([]);
const [pendingTimeRemaining, setPendingTimeRemaining] = useState<number | undefined>();
const undoPendingFnRef = useRef<() => void>(() => {});
/**
* Custom hook for managing pending signature deletions and undo countdown.
*/
function useSignatureUndo(
systemId: string | undefined,
settings: SignatureSettingsType,
outCommand: OutCommandHandler,
) {
const [countdown, setCountdown] = useState<number>(0);
const [pendingIds, setPendingIds] = useState<Set<string>>(new Set());
const [deletedSignatures, setDeletedSignatures] = useState<ExtendedSystemSignature[]>([]);
const intervalRef = useRef<number | null>(null);
const {
data: { selectedSystems },
} = useMapRootState();
const [currentSettings, setCurrentSettings] = useLocalStorageState(SIGNATURE_SETTING_STORE_KEY, {
defaultValue: SETTINGS_VALUES,
});
const handleSigCountChange = useCallback((count: number) => {
setSigCount(count);
const addDeleted = useCallback((signatures: ExtendedSystemSignature[]) => {
const newIds = signatures.map(sig => sig.eve_id);
setPendingIds(prev => {
const next = new Set(prev);
newIds.forEach(id => next.add(id));
return next;
});
setDeletedSignatures(prev => [...prev, ...signatures]);
}, []);
const [systemId] = selectedSystems;
const isNotSelectedSystem = selectedSystems.length !== 1;
const handleSettingsChange = useCallback((newSettings: SignatureSettingsType) => {
setCurrentSettings(newSettings);
setVisible(false);
}, []);
const handleLazyDeleteChange = useCallback((value: boolean) => {
setCurrentSettings(prev => ({ ...prev, [SETTINGS_KEYS.LAZY_DELETE_SIGNATURES]: value }));
}, []);
useHotkey(true, ['z'], event => {
if (pendingSigs.length > 0) {
event.preventDefault();
event.stopPropagation();
undoPendingFnRef.current();
setPendingSigs([]);
setPendingTimeRemaining(undefined);
}
});
const handleUndoClick = useCallback(() => {
undoPendingFnRef.current();
setPendingSigs([]);
setPendingTimeRemaining(undefined);
}, []);
const handleSettingsButtonClick = useCallback(() => {
setVisible(true);
}, []);
const handlePendingChange = useCallback(
(pending: React.MutableRefObject<Record<string, ExtendedSystemSignature>>, newUndo: () => void) => {
setPendingSigs(() => {
return Object.values(pending.current).filter(sig => sig.pendingDeletion);
});
undoPendingFnRef.current = newUndo;
},
[],
);
// Calculate the minimum time remaining for any pending signature
// Clear deleted signatures when system changes
useEffect(() => {
if (pendingSigs.length === 0) {
setPendingTimeRemaining(undefined);
if (systemId) {
setDeletedSignatures([]);
setPendingIds(new Set());
setCountdown(0);
if (intervalRef.current != null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
}
}, [systemId]);
// kick off or clear countdown whenever pendingIds changes
useEffect(() => {
// clear any existing timer
if (intervalRef.current != null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
if (pendingIds.size === 0) {
setCountdown(0);
setDeletedSignatures([]);
return;
}
const calculate = () => {
setPendingTimeRemaining(() => calculateTimeRemaining(pendingSigs));
};
// determine timeout from settings
const timeoutMs = getDeletionTimeoutMs(settings);
calculate();
const interval = setInterval(calculate, 1000);
return () => clearInterval(interval);
}, [pendingSigs]);
setCountdown(Math.ceil(timeoutMs / 1000));
// start new interval
intervalRef.current = window.setInterval(() => {
setCountdown(prev => {
if (prev <= 1) {
clearInterval(intervalRef.current!);
intervalRef.current = null;
setPendingIds(new Set());
setDeletedSignatures([]);
return 0;
}
return prev - 1;
});
}, 1000);
return () => {
if (intervalRef.current != null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
};
}, [pendingIds, settings]);
// undo handler
const handleUndo = useCallback(async () => {
if (!systemId || pendingIds.size === 0) return;
await outCommand({
type: OutCommand.undoDeleteSignatures,
data: { system_id: systemId, eve_ids: Array.from(pendingIds) },
});
setPendingIds(new Set());
setDeletedSignatures([]);
setCountdown(0);
if (intervalRef.current != null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
}, [systemId, pendingIds, outCommand]);
return {
pendingIds,
countdown,
deletedSignatures,
addDeleted,
handleUndo,
};
}
export const SystemSignatures = () => {
const [visible, setVisible] = useState(false);
const [sigCount, setSigCount] = useState(0);
const {
data: { selectedSystems },
outCommand,
} = useMapRootState();
const [currentSettings, setCurrentSettings] = useLocalStorageState<SignatureSettingsType>(
SIGNATURE_SETTING_STORE_KEY,
{
defaultValue: SETTINGS_VALUES,
},
);
const [systemId] = selectedSystems;
const isSystemSelected = useMemo(() => selectedSystems.length === 1, [selectedSystems.length]);
const { pendingIds, countdown, deletedSignatures, addDeleted, handleUndo } = useSignatureUndo(
systemId,
currentSettings,
outCommand,
);
useHotkey(true, ['z', 'Z'], (event: KeyboardEvent) => {
if (pendingIds.size > 0 && countdown > 0) {
event.preventDefault();
event.stopPropagation();
handleUndo();
}
});
const handleCountChange = useCallback((count: number) => {
setSigCount(count);
}, []);
const handleSettingsSave = useCallback(
(newSettings: SignatureSettingsType) => {
setCurrentSettings(newSettings);
setVisible(false);
},
[setCurrentSettings],
);
const handleLazyDeleteToggle = useCallback(
(value: boolean) => {
setCurrentSettings(prev => ({
...prev,
[SETTINGS_KEYS.LAZY_DELETE_SIGNATURES]: value,
}));
},
[setCurrentSettings],
);
const openSettings = useCallback(() => setVisible(true), []);
return (
<Widget
@@ -101,16 +181,16 @@ export const SystemSignatures = () => {
<SystemSignaturesHeader
sigCount={sigCount}
lazyDeleteValue={currentSettings[SETTINGS_KEYS.LAZY_DELETE_SIGNATURES] as boolean}
pendingCount={pendingSigs.length}
pendingTimeRemaining={pendingTimeRemaining}
onLazyDeleteChange={handleLazyDeleteChange}
onUndoClick={handleUndoClick}
onSettingsClick={handleSettingsButtonClick}
pendingCount={pendingIds.size}
undoCountdown={countdown}
onLazyDeleteChange={handleLazyDeleteToggle}
onUndoClick={handleUndo}
onSettingsClick={openSettings}
/>
}
windowId={SIGNATURE_WINDOW_ID}
>
{isNotSelectedSystem ? (
{!isSystemSelected ? (
<div className="w-full h-full flex justify-center items-center select-none text-center text-stone-400/80 text-sm">
System is not selected
</div>
@@ -118,22 +198,18 @@ export const SystemSignatures = () => {
<SystemSignaturesContent
systemId={systemId}
settings={currentSettings}
deletionTiming={
SIGNATURE_DELETION_TIMEOUTS[
(currentSettings[SETTINGS_KEYS.DELETION_TIMING] as keyof typeof SIGNATURE_DELETION_TIMEOUTS) ||
SIGNATURES_DELETION_TIMING.DEFAULT
] as number
}
onLazyDeleteChange={handleLazyDeleteChange}
onCountChange={handleSigCountChange}
onPendingChange={handlePendingChange}
deletedSignatures={deletedSignatures}
onLazyDeleteChange={handleLazyDeleteToggle}
onCountChange={handleCountChange}
onSignatureDeleted={addDeleted}
/>
)}
{visible && (
<SystemSignatureSettingsDialog
settings={currentSettings}
onCancel={() => setVisible(false)}
onSave={handleSettingsChange}
onSave={handleSettingsSave}
/>
)}
</Widget>

View File

@@ -57,12 +57,9 @@ interface SystemSignaturesContentProps {
onSelect?: (signature: SystemSignature) => void;
onLazyDeleteChange?: (value: boolean) => void;
onCountChange?: (count: number) => void;
onPendingChange?: (
pending: React.MutableRefObject<Record<string, ExtendedSystemSignature>>,
undo: () => void,
) => void;
deletionTiming?: number;
filterSignature?: (signature: SystemSignature) => boolean;
onSignatureDeleted?: (deletedSignatures: ExtendedSystemSignature[]) => void;
deletedSignatures?: ExtendedSystemSignature[];
}
export const SystemSignaturesContent = ({
@@ -73,9 +70,9 @@ export const SystemSignaturesContent = ({
onSelect,
onLazyDeleteChange,
onCountChange,
onPendingChange,
deletionTiming,
filterSignature,
onSignatureDeleted,
deletedSignatures = [],
}: SystemSignaturesContentProps) => {
const [selectedSignatureForDialog, setSelectedSignatureForDialog] = useState<SystemSignature | null>(null);
const [showSignatureSettings, setShowSignatureSettings] = useState(false);
@@ -95,15 +92,21 @@ export const SystemSignaturesContent = ({
{ defaultValue: SORT_DEFAULT_VALUES },
);
const { signatures, selectedSignatures, setSelectedSignatures, handleDeleteSelected, handleSelectAll, handlePaste } =
useSystemSignaturesData({
systemId,
settings,
onCountChange,
onPendingChange,
onLazyDeleteChange,
deletionTiming,
});
const {
signatures,
selectedSignatures,
setSelectedSignatures,
handleDeleteSelected,
handleSelectAll,
handlePaste,
hasUnsupportedLanguage,
} = useSystemSignaturesData({
systemId,
settings,
onCountChange,
onLazyDeleteChange,
onSignatureDeleted,
});
useEffect(() => {
if (selectable) return;
@@ -125,6 +128,8 @@ export const SystemSignaturesContent = ({
event.preventDefault();
event.stopPropagation();
// Delete key should always immediately delete, never show pending deletions
handleDeleteSelected();
});
@@ -153,9 +158,16 @@ export const SystemSignaturesContent = ({
const handleSelectSignatures = useCallback(
(e: { value: SystemSignature[] }) => {
selectable ? onSelect?.(e.value[0]) : setSelectedSignatures(e.value as ExtendedSystemSignature[]);
// Filter out deleted signatures from selection
const selectableSignatures = e.value.filter(
sig => !deletedSignatures.some(deleted => deleted.eve_id === sig.eve_id),
);
selectable
? onSelect?.(selectableSignatures[0])
: setSelectedSignatures(selectableSignatures as ExtendedSystemSignature[]);
},
[selectable],
[onSelect, selectable, setSelectedSignatures, deletedSignatures],
);
const { showDescriptionColumn, showUpdatedColumn, showCharacterColumn, showCharacterPortrait } = useMemo(
@@ -169,7 +181,11 @@ export const SystemSignaturesContent = ({
);
const filteredSignatures = useMemo<ExtendedSystemSignature[]>(() => {
return signatures.filter(sig => {
// Get the set of deleted signature IDs for quick lookup
const deletedIds = new Set(deletedSignatures.map(sig => sig.eve_id));
// Common filter function
const shouldShowSignature = (sig: ExtendedSystemSignature): boolean => {
if (filterSignature && !filterSignature(sig)) {
return false;
}
@@ -188,15 +204,37 @@ export const SystemSignaturesContent = ({
x => GROUPS_LIST.includes(x as SignatureGroup) && settings[x as SETTINGS_KEYS],
);
return enabledGroups.includes(getGroupIdByRawGroup(sig.group));
const mappedGroup = getGroupIdByRawGroup(sig.group);
if (!mappedGroup) {
return true; // If we can't determine the group, still show it
}
return enabledGroups.includes(mappedGroup);
}
return true;
}
return settings[sig.kind];
return settings[sig.kind] as boolean;
};
// Filter active signatures, excluding any that are in the deleted list
const activeSignatures = signatures.filter(sig => {
// Skip if this signature is in the deleted list
if (deletedIds.has(sig.eve_id)) {
return false;
}
return shouldShowSignature(sig);
});
}, [signatures, hideLinkedSignatures, settings, filterSignature]);
// Add deleted signatures with pending deletion flag, applying the same filters
const deletedWithPendingFlag = deletedSignatures.filter(shouldShowSignature).map(sig => ({
...sig,
pendingDeletion: true,
}));
return [...activeSignatures, ...deletedWithPendingFlag];
}, [signatures, hideLinkedSignatures, settings, filterSignature, deletedSignatures]);
const onRowMouseEnter = useCallback((e: DataTableRowMouseEvent) => {
setHoveredSignature(e.data as SystemSignature);
@@ -236,113 +274,122 @@ export const SystemSignaturesContent = ({
No signatures
</div>
) : (
<DataTable
value={filteredSignatures}
size="small"
selectionMode="multiple"
selection={selectedSignatures}
metaKeySelection
onSelectionChange={handleSelectSignatures}
dataKey="eve_id"
className="w-full select-none"
resizableColumns={false}
rowHover
selectAll
onRowDoubleClick={handleRowClick}
sortField={sortSettings.sortField}
sortOrder={sortSettings.sortOrder}
onSort={handleSortSettings}
onRowMouseEnter={onRowMouseEnter}
onRowMouseLeave={onRowMouseLeave}
// @ts-ignore
rowClassName={getRowClassName}
>
<Column
field="icon"
header=""
body={renderColIcon}
bodyClassName="p-0 px-1"
style={{ maxWidth: 26, minWidth: 26, width: 26 }}
/>
<Column
field="eve_id"
header="Id"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: 72, minWidth: 72, width: 72 }}
sortable
/>
<Column
field="group"
header="Group"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: 110, minWidth: 110, width: 110 }}
body={sig => sig.group ?? ''}
hidden={isCompact}
sortable
/>
<Column
field="info"
header="Info"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: nameColumnWidth }}
hidden={isCompact || isMedium}
body={renderInfoColumn}
/>
{showDescriptionColumn && (
<Column
field="description"
header="Description"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
hidden={isCompact}
body={renderDescription}
sortable
/>
<>
{hasUnsupportedLanguage && (
<div className="w-full flex justify-center items-center text-amber-500 text-xs p-1 bg-amber-950/20 border-b border-amber-800/30">
<i className={PrimeIcons.EXCLAMATION_TRIANGLE + ' mr-1'} />
Non-English signatures detected. Some signatures may not display correctly. Double-click to edit signature
details.
</div>
)}
<Column
field="inserted_at"
header="Added"
dataType="date"
body={renderAddedTimeLeft}
style={{ minWidth: 70, maxWidth: 80 }}
bodyClassName="ssc-header text-ellipsis overflow-hidden whitespace-nowrap"
sortable
/>
{showUpdatedColumn && (
<Column
field="updated_at"
header="Updated"
dataType="date"
body={renderUpdatedTimeLeft}
style={{ minWidth: 70, maxWidth: 80 }}
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
sortable
/>
)}
{showCharacterColumn && (
<Column
field="character_name"
header="Character"
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
sortable
></Column>
)}
{!selectable && (
<DataTable
value={filteredSignatures}
size="small"
selectionMode="multiple"
selection={selectedSignatures}
metaKeySelection
onSelectionChange={handleSelectSignatures}
dataKey="eve_id"
className="w-full select-none"
resizableColumns={false}
rowHover
selectAll
onRowDoubleClick={handleRowClick}
sortField={sortSettings.sortField}
sortOrder={sortSettings.sortOrder}
onSort={handleSortSettings}
onRowMouseEnter={onRowMouseEnter}
onRowMouseLeave={onRowMouseLeave}
// @ts-ignore
rowClassName={getRowClassName}
>
<Column
field="icon"
header=""
body={() => (
<div className="flex justify-end items-center gap-2 mr-[4px]">
<WdTooltipWrapper content="Double-click a row to edit signature">
<span className={PrimeIcons.PENCIL + ' text-[10px]'} />
</WdTooltipWrapper>
</div>
)}
body={renderColIcon}
bodyClassName="p-0 px-1"
style={{ maxWidth: 26, minWidth: 26, width: 26 }}
bodyClassName="p-0 pl-1 pr-2"
/>
)}
</DataTable>
<Column
field="eve_id"
header="Id"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: 72, minWidth: 72, width: 72 }}
sortable
/>
<Column
field="group"
header="Group"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: 110, minWidth: 110, width: 110 }}
body={sig => sig.group ?? ''}
hidden={isCompact}
sortable
/>
<Column
field="info"
header="Info"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
style={{ maxWidth: nameColumnWidth }}
hidden={isCompact || isMedium}
body={renderInfoColumn}
/>
{showDescriptionColumn && (
<Column
field="description"
header="Description"
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
hidden={isCompact}
body={renderDescription}
sortable
/>
)}
<Column
field="inserted_at"
header="Added"
dataType="date"
body={renderAddedTimeLeft}
style={{ minWidth: 70, maxWidth: 80 }}
bodyClassName="ssc-header text-ellipsis overflow-hidden whitespace-nowrap"
sortable
/>
{showUpdatedColumn && (
<Column
field="updated_at"
header="Updated"
dataType="date"
body={renderUpdatedTimeLeft}
style={{ minWidth: 70, maxWidth: 80 }}
bodyClassName="text-ellipsis overflow-hidden whitespace-nowrap"
sortable
/>
)}
{showCharacterColumn && (
<Column
field="character_name"
header="Character"
bodyClassName="w-[70px] text-ellipsis overflow-hidden whitespace-nowrap"
sortable
></Column>
)}
{!selectable && (
<Column
header=""
body={() => (
<div className="flex justify-end items-center gap-2 mr-[4px]">
<WdTooltipWrapper content="Double-click a row to edit signature">
<span className={PrimeIcons.PENCIL + ' text-[10px]'} />
</WdTooltipWrapper>
</div>
)}
style={{ maxWidth: 26, minWidth: 26, width: 26 }}
bodyClassName="p-0 pl-1 pr-2"
/>
)}
</DataTable>
</>
)}
<WdTooltip

View File

@@ -1,10 +1,14 @@
import {
GroupType,
SignatureGroup,
SignatureGroupDE,
SignatureGroupENG,
SignatureGroupFR,
SignatureGroupRU,
SignatureKind,
SignatureKindDE,
SignatureKindENG,
SignatureKindFR,
SignatureKindRU,
} from '@/hooks/Mapper/types';
@@ -40,46 +44,58 @@ export const GROUPS: Record<SignatureGroup, GroupType> = {
[SignatureGroup.CosmicSignature]: { id: SignatureGroup.CosmicSignature, icon: '/icons/x_close14.png', w: 9, h: 9 },
};
export const MAPPING_GROUP_TO_ENG = {
// ENGLISH
[SignatureGroupENG.GasSite]: SignatureGroup.GasSite,
[SignatureGroupENG.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupENG.DataSite]: SignatureGroup.DataSite,
[SignatureGroupENG.OreSite]: SignatureGroup.OreSite,
[SignatureGroupENG.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupENG.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupENG.CosmicSignature]: SignatureGroup.CosmicSignature,
// RUSSIAN
[SignatureGroupRU.GasSite]: SignatureGroup.GasSite,
[SignatureGroupRU.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupRU.DataSite]: SignatureGroup.DataSite,
[SignatureGroupRU.OreSite]: SignatureGroup.OreSite,
[SignatureGroupRU.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupRU.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupRU.CosmicSignature]: SignatureGroup.CosmicSignature,
export const LANGUAGE_GROUP_MAPPINGS = {
EN: {
[SignatureGroupENG.GasSite]: SignatureGroup.GasSite,
[SignatureGroupENG.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupENG.DataSite]: SignatureGroup.DataSite,
[SignatureGroupENG.OreSite]: SignatureGroup.OreSite,
[SignatureGroupENG.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupENG.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupENG.CosmicSignature]: SignatureGroup.CosmicSignature,
},
RU: {
[SignatureGroupRU.GasSite]: SignatureGroup.GasSite,
[SignatureGroupRU.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupRU.DataSite]: SignatureGroup.DataSite,
[SignatureGroupRU.OreSite]: SignatureGroup.OreSite,
[SignatureGroupRU.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupRU.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupRU.CosmicSignature]: SignatureGroup.CosmicSignature,
},
FR: {
[SignatureGroupFR.GasSite]: SignatureGroup.GasSite,
[SignatureGroupFR.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupFR.DataSite]: SignatureGroup.DataSite,
[SignatureGroupFR.OreSite]: SignatureGroup.OreSite,
[SignatureGroupFR.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupFR.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupFR.CosmicSignature]: SignatureGroup.CosmicSignature,
},
DE: {
[SignatureGroupDE.GasSite]: SignatureGroup.GasSite,
[SignatureGroupDE.RelicSite]: SignatureGroup.RelicSite,
[SignatureGroupDE.DataSite]: SignatureGroup.DataSite,
[SignatureGroupDE.OreSite]: SignatureGroup.OreSite,
[SignatureGroupDE.CombatSite]: SignatureGroup.CombatSite,
[SignatureGroupDE.Wormhole]: SignatureGroup.Wormhole,
[SignatureGroupDE.CosmicSignature]: SignatureGroup.CosmicSignature,
},
};
export const MAPPING_TYPE_TO_ENG = {
// ENGLISH
[SignatureKindENG.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindENG.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindENG.Structure]: SignatureKind.Structure,
[SignatureKindENG.Ship]: SignatureKind.Ship,
[SignatureKindENG.Deployable]: SignatureKind.Deployable,
[SignatureKindENG.Drone]: SignatureKind.Drone,
// Flatten the structure for backward compatibility
export const MAPPING_GROUP_TO_ENG: Record<string, SignatureGroup> = (() => {
const flattened: Record<string, SignatureGroup> = {};
for (const [, mappings] of Object.entries(LANGUAGE_GROUP_MAPPINGS)) {
Object.assign(flattened, mappings);
}
return flattened;
})();
// RUSSIAN
[SignatureKindRU.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindRU.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindRU.Structure]: SignatureKind.Structure,
[SignatureKindRU.Ship]: SignatureKind.Ship,
[SignatureKindRU.Deployable]: SignatureKind.Deployable,
[SignatureKindRU.Drone]: SignatureKind.Drone,
export const getGroupIdByRawGroup = (val: string): SignatureGroup | undefined => {
return MAPPING_GROUP_TO_ENG[val] || undefined;
};
export const getGroupIdByRawGroup = (val: string) => MAPPING_GROUP_TO_ENG[val as SignatureGroup];
export const SIGNATURE_WINDOW_ID = 'system_signatures_window';
export const SIGNATURE_SETTING_STORE_KEY = 'wanderer_system_signature_settings_v6_5';
@@ -123,7 +139,7 @@ export type Setting = {
name: string;
type: SettingsTypes;
isSeparator?: boolean;
options?: { label: string; value: any }[];
options?: { label: string; value: number | string | boolean }[];
};
export enum SIGNATURES_DELETION_TIMING {
@@ -132,7 +148,8 @@ export enum SIGNATURES_DELETION_TIMING {
EXTENDED,
}
export type SignatureDeletionTimingType = { [key in SIGNATURES_DELETION_TIMING]?: unknown };
// Now use a stricter type: every timing key maps to a number
export type SignatureDeletionTimingType = Record<SIGNATURES_DELETION_TIMING, number>;
export const SIGNATURE_SETTINGS = {
filterFlags: [
@@ -203,8 +220,73 @@ export const SETTINGS_VALUES: SignatureSettingsType = {
[SETTINGS_KEYS.COMBAT_SITE]: true,
};
// Now this map is strongly typed as “number” for each timing enum
export const SIGNATURE_DELETION_TIMEOUTS: SignatureDeletionTimingType = {
[SIGNATURES_DELETION_TIMING.DEFAULT]: 10_000,
[SIGNATURES_DELETION_TIMING.IMMEDIATE]: 0,
[SIGNATURES_DELETION_TIMING.DEFAULT]: 10_000,
[SIGNATURES_DELETION_TIMING.EXTENDED]: 30_000,
};
/**
* Helper function to extract the deletion timeout in milliseconds from settings
*/
export function getDeletionTimeoutMs(settings: SignatureSettingsType): number {
const raw = settings[SETTINGS_KEYS.DELETION_TIMING];
const timing =
raw && typeof raw === 'object' && 'value' in raw
? (raw as { value: SIGNATURES_DELETION_TIMING }).value
: (raw as SIGNATURES_DELETION_TIMING | undefined);
const validTiming = typeof timing === 'number' ? timing : SIGNATURES_DELETION_TIMING.DEFAULT;
return SIGNATURE_DELETION_TIMEOUTS[validTiming];
}
// Replace the flat structure with a nested structure by language
export const LANGUAGE_TYPE_MAPPINGS = {
EN: {
[SignatureKindENG.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindENG.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindENG.Structure]: SignatureKind.Structure,
[SignatureKindENG.Ship]: SignatureKind.Ship,
[SignatureKindENG.Deployable]: SignatureKind.Deployable,
[SignatureKindENG.Drone]: SignatureKind.Drone,
[SignatureKindENG.Starbase]: SignatureKind.Starbase,
},
RU: {
[SignatureKindRU.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindRU.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindRU.Structure]: SignatureKind.Structure,
[SignatureKindRU.Ship]: SignatureKind.Ship,
[SignatureKindRU.Deployable]: SignatureKind.Deployable,
[SignatureKindRU.Drone]: SignatureKind.Drone,
[SignatureKindRU.Starbase]: SignatureKind.Starbase,
},
FR: {
[SignatureKindFR.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindFR.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindFR.Structure]: SignatureKind.Structure,
[SignatureKindFR.Ship]: SignatureKind.Ship,
[SignatureKindFR.Deployable]: SignatureKind.Deployable,
[SignatureKindFR.Drone]: SignatureKind.Drone,
[SignatureKindFR.Starbase]: SignatureKind.Starbase,
},
DE: {
[SignatureKindDE.CosmicSignature]: SignatureKind.CosmicSignature,
[SignatureKindDE.CosmicAnomaly]: SignatureKind.CosmicAnomaly,
[SignatureKindDE.Structure]: SignatureKind.Structure,
[SignatureKindDE.Ship]: SignatureKind.Ship,
[SignatureKindDE.Deployable]: SignatureKind.Deployable,
[SignatureKindDE.Drone]: SignatureKind.Drone,
[SignatureKindDE.Starbase]: SignatureKind.Starbase,
},
};
// Flatten the structure for backward compatibility
export const MAPPING_TYPE_TO_ENG: Record<string, SignatureKind> = (() => {
const flattened: Record<string, SignatureKind> = {};
for (const [, mappings] of Object.entries(LANGUAGE_TYPE_MAPPINGS)) {
Object.assign(flattened, mappings);
}
return flattened;
})();

View File

@@ -1,5 +1,5 @@
import { SystemSignature } from '@/hooks/Mapper/types';
import { GROUPS_LIST } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants';
import { SystemSignature } from '@/hooks/Mapper/types';
import { getState } from './getState';
/**
@@ -22,6 +22,7 @@ export const getActualSigs = (
oldSignatures.forEach(oldSig => {
const newSig = newSignatures.find(s => s.eve_id === oldSig.eve_id);
if (newSig) {
const needUpgrade = getState(GROUPS_LIST, newSig) > getState(GROUPS_LIST, oldSig);
const mergedSig = { ...oldSig };

View File

@@ -1,13 +1,15 @@
import { SystemSignature } from '@/hooks/Mapper/types';
import { UNKNOWN_SIGNATURE_NAME } from '@/hooks/Mapper/helpers';
import { SignatureGroup, SystemSignature } from '@/hooks/Mapper/types';
export const getState = (_: string[], newSig: SystemSignature) => {
let state = -1;
if (!newSig.group) {
if (!newSig.group || newSig.group === SignatureGroup.CosmicSignature) {
state = 0;
} else if (!newSig.name || newSig.name === '') {
} else if (!newSig.name || newSig.name === '' || newSig.name === UNKNOWN_SIGNATURE_NAME) {
state = 1;
} else if (newSig.name !== '') {
state = 2;
}
return state;
};

View File

@@ -1,23 +1,18 @@
import { useCallback, useRef, useEffect } from 'react';
import { useCallback, useRef } from 'react';
import { OutCommand } from '@/hooks/Mapper/types/mapHandlers';
import { prepareUpdatePayload, scheduleLazyTimers } from '../helpers';
import { prepareUpdatePayload } from '../helpers';
import { UsePendingDeletionParams } from './types';
import { FINAL_DURATION_MS } from '../constants';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { ExtendedSystemSignature } from '@/hooks/Mapper/types';
export function usePendingDeletions({
systemId,
setSignatures,
deletionTiming,
onPendingChange,
}: UsePendingDeletionParams) {
}: Omit<UsePendingDeletionParams, 'deletionTiming'>) {
const { outCommand } = useMapRootState();
const pendingDeletionMapRef = useRef<Record<string, ExtendedSystemSignature>>({});
// Use the provided deletion timing or fall back to the default
const finalDuration = deletionTiming !== undefined ? deletionTiming : FINAL_DURATION_MS;
const processRemovedSignatures = useCallback(
async (
removed: ExtendedSystemSignature[],
@@ -25,63 +20,15 @@ export function usePendingDeletions({
updated: ExtendedSystemSignature[],
) => {
if (!removed.length) return;
// If deletion timing is 0, immediately delete without pending state
if (finalDuration === 0) {
await outCommand({
type: OutCommand.updateSignatures,
data: prepareUpdatePayload(systemId, added, updated, removed),
});
return;
}
const now = Date.now();
const processedRemoved = removed.map(r => ({
...r,
pendingDeletion: true,
pendingUntil: now + finalDuration,
}));
pendingDeletionMapRef.current = {
...pendingDeletionMapRef.current,
...processedRemoved.reduce((acc: any, sig) => {
acc[sig.eve_id] = sig;
return acc;
}, {}),
};
onPendingChange?.(pendingDeletionMapRef, clearPendingDeletions);
setSignatures(prev =>
prev.map(sig => {
if (processedRemoved.find(r => r.eve_id === sig.eve_id)) {
return { ...sig, pendingDeletion: true, pendingUntil: now + finalDuration };
}
return sig;
}),
);
scheduleLazyTimers(
processedRemoved,
pendingDeletionMapRef,
async sig => {
await outCommand({
type: OutCommand.updateSignatures,
data: prepareUpdatePayload(systemId, [], [], [sig]),
});
delete pendingDeletionMapRef.current[sig.eve_id];
setSignatures(prev => prev.filter(x => x.eve_id !== sig.eve_id));
onPendingChange?.(pendingDeletionMapRef, clearPendingDeletions);
},
finalDuration,
);
await outCommand({
type: OutCommand.updateSignatures,
data: prepareUpdatePayload(systemId, added, updated, removed),
});
},
[systemId, outCommand, finalDuration],
[systemId, outCommand],
);
const clearPendingDeletions = useCallback(() => {
Object.values(pendingDeletionMapRef.current).forEach(({ finalTimeoutId }) => {
clearTimeout(finalTimeoutId);
});
pendingDeletionMapRef.current = {};
setSignatures(prev => prev.map(x => (x.pendingDeletion ? { ...x, pendingDeletion: false } : x)));
onPendingChange?.(pendingDeletionMapRef, clearPendingDeletions);

View File

@@ -5,7 +5,10 @@ import { OutCommand } from '@/hooks/Mapper/types/mapHandlers';
import { useCallback, useEffect, useState } from 'react';
import useRefState from 'react-usestateref';
import { SETTINGS_KEYS } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
import {
SETTINGS_KEYS,
getDeletionTimeoutMs,
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { getActualSigs } from '../helpers';
import { UseSystemSignaturesDataProps } from './types';
@@ -18,16 +21,18 @@ export const useSystemSignaturesData = ({
onCountChange,
onPendingChange,
onLazyDeleteChange,
deletionTiming,
}: UseSystemSignaturesDataProps) => {
onSignatureDeleted,
}: Omit<UseSystemSignaturesDataProps, 'deletionTiming'> & {
onSignatureDeleted?: (deletedSignatures: ExtendedSystemSignature[]) => void;
}) => {
const { outCommand } = useMapRootState();
const [signatures, setSignatures, signaturesRef] = useRefState<ExtendedSystemSignature[]>([]);
const [selectedSignatures, setSelectedSignatures] = useState<ExtendedSystemSignature[]>([]);
const [hasUnsupportedLanguage, setHasUnsupportedLanguage] = useState<boolean>(false);
const { pendingDeletionMapRef, processRemovedSignatures, clearPendingDeletions } = usePendingDeletions({
systemId,
setSignatures,
deletionTiming,
onPendingChange,
});
@@ -42,6 +47,7 @@ export const useSystemSignaturesData = ({
async (clipboardString: string) => {
const lazyDeleteValue = settings[SETTINGS_KEYS.LAZY_DELETE_SIGNATURES] as boolean;
// Parse the incoming signatures
const incomingSignatures = parseSignatures(
clipboardString,
Object.keys(settings).filter(skey => skey in SignatureKind),
@@ -51,14 +57,37 @@ export const useSystemSignaturesData = ({
return;
}
// Check if any signatures might be using unsupported languages
// This is a basic heuristic: if we have signatures where the original group wasn't mapped
const clipboardRows = clipboardString.split('\n').filter(row => row.trim() !== '');
const detectedSignatureCount = clipboardRows.filter(row => row.match(/^[A-Z]{3}-\d{3}/)).length;
// If we detected valid IDs but got fewer parsed signatures, we might have language issues
if (detectedSignatureCount > 0 && incomingSignatures.length < detectedSignatureCount) {
setHasUnsupportedLanguage(true);
} else {
setHasUnsupportedLanguage(false);
}
const currentNonPending = lazyDeleteValue
? signaturesRef.current.filter(sig => !sig.pendingDeletion)
: signaturesRef.current.filter(sig => !sig.pendingDeletion || !sig.pendingAddition);
const { added, updated, removed } = getActualSigs(currentNonPending, incomingSignatures, !lazyDeleteValue, true);
const { added, updated, removed } = getActualSigs(currentNonPending, incomingSignatures, !lazyDeleteValue, false);
if (removed.length > 0) {
await processRemovedSignatures(removed, added, updated);
// Only show pending deletions if:
// 1. Lazy deletion is enabled AND
// 2. Deletion timing is not immediate (> 0)
if (onSignatureDeleted && lazyDeleteValue) {
const timeoutMs = getDeletionTimeoutMs(settings);
if (timeoutMs > 0) {
onSignatureDeleted(removed);
}
}
}
if (updated.length !== 0 || added.length !== 0) {
@@ -78,17 +107,23 @@ export const useSystemSignaturesData = ({
onLazyDeleteChange?.(false);
}
},
[settings, signaturesRef, processRemovedSignatures, outCommand, systemId, onLazyDeleteChange],
[settings, signaturesRef, processRemovedSignatures, outCommand, systemId, onLazyDeleteChange, onSignatureDeleted],
);
const handleDeleteSelected = useCallback(async () => {
if (!selectedSignatures.length) return;
const selectedIds = selectedSignatures.map(s => s.eve_id);
const finalList = signatures.filter(s => !selectedIds.includes(s.eve_id));
// IMPORTANT: Send deletion to server BEFORE updating local state
// Otherwise signaturesRef.current will be updated and getActualSigs won't detect removals
await handleUpdateSignatures(finalList, false, true);
// Update local state after server call
setSignatures(finalList);
setSelectedSignatures([]);
}, [selectedSignatures, signatures]);
}, [handleUpdateSignatures, selectedSignatures, signatures, setSignatures]);
const handleSelectAll = useCallback(() => {
setSelectedSignatures(signatures);
@@ -119,11 +154,12 @@ export const useSystemSignaturesData = ({
}, [signatures]);
return {
signatures,
signatures: signatures.filter(sig => !sig.deleted),
selectedSignatures,
setSelectedSignatures,
handleDeleteSelected,
handleSelectAll,
handlePaste,
hasUnsupportedLanguage,
};
};

View File

@@ -2,7 +2,6 @@ import { Commands, OutCommand } from '@/hooks/Mapper/types';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import {
AddHubCommand,
LoadRoutesCommand,
RoutesImperativeHandle,
} from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/types.ts';
import { useCallback, useRef } from 'react';
@@ -13,24 +12,11 @@ export const WRoutesPublic = () => {
const {
outCommand,
storedSettings: { settingsRoutes, settingsRoutesUpdate },
data: { hubs, routes },
data: { hubs, routes, loadingPublicRoutes },
} = useMapRootState();
const ref = useRef<RoutesImperativeHandle>(null);
const loadRoutesCommand: LoadRoutesCommand = useCallback(
async (systemId, routesSettings) => {
outCommand({
type: OutCommand.getRoutes,
data: {
system_id: systemId,
routes_settings: routesSettings,
},
});
},
[outCommand],
);
const addHubCommand: AddHubCommand = useCallback(
async systemId => {
if (hubs.includes(systemId)) {
@@ -72,10 +58,10 @@ export const WRoutesPublic = () => {
ref={ref}
title="Routes"
data={settingsRoutes}
loading={loadingPublicRoutes}
update={settingsRoutesUpdate}
hubs={hubs}
routesList={routes}
loadRoutesCommand={loadRoutesCommand}
addHubCommand={addHubCommand}
toggleHubCommand={toggleHubCommand}
/>

View File

@@ -8,6 +8,7 @@ import {
import { useCallback, useRef } from 'react';
import { RoutesWidget } from '@/hooks/Mapper/components/mapInterface/widgets';
import { useMapEventListener } from '@/hooks/Mapper/events';
import { useLoadRoutes } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/hooks';
export const WRoutesUser = () => {
const {
@@ -61,9 +62,17 @@ export const WRoutesUser = () => {
[userHubs, outCommand],
);
// INFO: User routes loading only if open widget with user routes
const { loading, setLoading } = useLoadRoutes({
data: settingsRoutes,
hubs: userHubs,
loadRoutesCommand,
routesList: userRoutes,
});
useMapEventListener(event => {
if (event.name === Commands.userRoutes) {
ref.current?.stopLoading();
setLoading(false);
}
return true;
});
@@ -76,7 +85,7 @@ export const WRoutesUser = () => {
update={settingsRoutesUpdate}
hubs={userHubs}
routesList={userRoutes}
loadRoutesCommand={loadRoutesCommand}
loading={loading}
addHubCommand={addHubCommand}
toggleHubCommand={toggleHubCommand}
isRestricted

View File

@@ -13,6 +13,7 @@ import { useCharacterActivityHandlers } from './hooks/useCharacterActivityHandle
import { TrackingDialog } from '@/hooks/Mapper/components/mapRootContent/components/TrackingDialog';
import { useMapEventListener } from '@/hooks/Mapper/events';
import { Commands } from '@/hooks/Mapper/types';
import { PingsInterface } from '@/hooks/Mapper/components/mapInterface/components';
export interface MapRootContentProps {}
@@ -62,17 +63,21 @@ export const MapRootContent = ({}: MapRootContentProps) => {
onShowOnTheMap={handleShowOnTheMap}
onShowMapSettings={handleShowMapSettings}
onShowTrackingDialog={handleShowTrackingDialog}
additionalContent={<PingsInterface hasLeftOffset />}
/>
</div>
</div>
) : (
<div className="absolute top-0 left-14 w-[calc(100%-3.5rem)] h-[calc(100%-3.5rem)] pointer-events-none">
<Topbar>
<MapContextMenu
onShowOnTheMap={handleShowOnTheMap}
onShowMapSettings={handleShowMapSettings}
onShowTrackingDialog={handleShowTrackingDialog}
/>
<div className="flex items-center ml-1">
<PingsInterface />
<MapContextMenu
onShowOnTheMap={handleShowOnTheMap}
onShowMapSettings={handleShowMapSettings}
onShowTrackingDialog={handleShowTrackingDialog}
/>
</div>
</Topbar>
{mapInterface}
</div>

View File

@@ -15,7 +15,10 @@ export interface MapContextMenuProps {
}
export const MapContextMenu = ({ onShowOnTheMap, onShowMapSettings, onShowTrackingDialog }: MapContextMenuProps) => {
const { outCommand, setInterfaceSettings } = useMapRootState();
const {
outCommand,
storedSettings: { setInterfaceSettings },
} = useMapRootState();
const canTrackCharacters = useMapCheckPermissions([UserPermission.TRACK_CHARACTER]);

View File

@@ -4,13 +4,7 @@ import { useCallback, useRef, useState } from 'react';
import { TabPanel, TabView } from 'primereact/tabview';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { OutCommand } from '@/hooks/Mapper/types';
import {
CONNECTIONS_CHECKBOXES_PROPS,
SIGNATURES_CHECKBOXES_PROPS,
SYSTEMS_CHECKBOXES_PROPS,
THEME_SETTING,
UI_CHECKBOXES_PROPS,
} from './constants.ts';
import { CONNECTIONS_CHECKBOXES_PROPS, SIGNATURES_CHECKBOXES_PROPS, SYSTEMS_CHECKBOXES_PROPS } from './constants.ts';
import {
MapSettingsProvider,
useMapSettings,
@@ -34,6 +28,8 @@ export const MapSettingsComp = ({ visible, onHide }: MapSettingsProps) => {
refVars.current = { outCommand, onHide, visible };
const handleShow = useCallback(async () => {
// TODO: need fix it - add type?
// @ts-ignore
const { user_settings } = await refVars.current.outCommand({
type: OutCommand.getUserSettings,
data: null,
@@ -88,17 +84,9 @@ export const MapSettingsComp = ({ visible, onHide }: MapSettingsProps) => {
{renderSettingsList(SIGNATURES_CHECKBOXES_PROPS)}
</TabPanel>
<TabPanel header="User Interface" headerClassName={styles.verticalTabHeader}>
{renderSettingsList(UI_CHECKBOXES_PROPS)}
</TabPanel>
<TabPanel header="Widgets" className="h-full" headerClassName={styles.verticalTabHeader}>
<WidgetsSettings />
</TabPanel>
<TabPanel header="Theme" headerClassName={styles.verticalTabHeader}>
{renderSettingItem(THEME_SETTING)}
</TabPanel>
</TabView>
</div>
</div>

View File

@@ -88,8 +88,9 @@ export const MapSettingsProvider = ({ children }: { children: ReactNode }) => {
if (item.type === 'dropdown' && item.options) {
return (
<div key={item.prop.toString()} className="flex items-center gap-2 mt-2">
<label className="text-sm">{item.label}:</label>
<div key={item.prop.toString()} className="grid grid-cols-[auto_1fr_auto] items-center">
<label className="text-[var(--gray-200)] text-[13px] select-none">{item.label}:</label>
<div className="border-b-2 border-dotted border-[#3f3f3f] h-px mx-3" />
<Dropdown
className="text-sm"
value={currentValue}

View File

@@ -1,13 +1,34 @@
import { COMMON_CHECKBOXES_PROPS } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/constants.ts';
import {
MINI_MAP_PLACEMENT,
PINGS_PLACEMENT,
THEME_SETTING,
UI_CHECKBOXES_PROPS,
} from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/constants.ts';
import { useMapSettings } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/MapSettingsProvider.tsx';
import { SettingsListItem } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/types.ts';
import { useCallback } from 'react';
export const CommonSettings = () => {
const { renderSettingItem } = useMapSettings();
const renderSettingsList = (list: SettingsListItem[]) => {
return list.map(renderSettingItem);
};
const renderSettingsList = useCallback(
(list: SettingsListItem[]) => {
return list.map(renderSettingItem);
},
[renderSettingItem],
);
return <div className="w-full h-full flex flex-col gap-1">{renderSettingsList(COMMON_CHECKBOXES_PROPS)}</div>;
return (
<div className="flex flex-col h-full gap-1">
<div>
<div className="w-full h-full flex flex-col gap-1">{renderSettingsList(UI_CHECKBOXES_PROPS)}</div>
</div>
<div className="border-b-2 border-dotted border-stone-700/50 h-px my-3" />
<div className="grid grid-cols-[1fr_auto]">{renderSettingItem(MINI_MAP_PLACEMENT)}</div>
<div className="grid grid-cols-[1fr_auto]">{renderSettingItem(PINGS_PLACEMENT)}</div>
<div className="grid grid-cols-[1fr_auto]">{renderSettingItem(THEME_SETTING)}</div>
</div>
);
};

View File

@@ -10,9 +10,9 @@ interface PrettySwitchboxProps {
export const PrettySwitchbox = ({ checked, setChecked, label }: PrettySwitchboxProps) => {
return (
<label className={styles.CheckboxContainer}>
<span>{label}</span>
<div />
<label className="grid grid-cols-[auto_1fr_auto] items-center">
<span className="text-[var(--gray-200)] text-[13px] select-none">{label}</span>
<div className="border-b-2 border-dotted border-[#3f3f3f] h-px mx-3" />
<div className={styles.smallInputSwitch}>
<WdCheckbox size="m" label={''} value={checked} onChange={e => setChecked(e.checked ?? false)} />
</div>

View File

@@ -1,6 +1,6 @@
import { SettingsListItem, UserSettingsRemoteProps } from './types.ts';
import { InterfaceStoredSettingsProps } from '@/hooks/Mapper/mapRootProvider';
import { AvailableThemes } from '@/hooks/Mapper/mapRootProvider/types.ts';
import { AvailableThemes, MiniMapPlacement, PingsPlacement } from '@/hooks/Mapper/mapRootProvider/types.ts';
export const DEFAULT_REMOTE_SETTINGS = {
[UserSettingsRemoteProps.link_signature_on_splash]: false,
@@ -14,13 +14,13 @@ export const UserSettingsRemoteList = [
UserSettingsRemoteProps.delete_connection_with_sigs,
];
export const COMMON_CHECKBOXES_PROPS: SettingsListItem[] = [
{
prop: InterfaceStoredSettingsProps.isShowMinimap,
label: 'Show Minimap',
type: 'checkbox',
},
];
// export const COMMON_CHECKBOXES_PROPS: SettingsListItem[] = [
// // {
// // prop: InterfaceStoredSettingsProps.isShowMinimap,
// // label: 'Show Minimap',
// // type: 'checkbox',
// // },
// ];
export const SYSTEMS_CHECKBOXES_PROPS: SettingsListItem[] = [
{
@@ -90,3 +90,32 @@ export const THEME_SETTING: SettingsListItem = {
type: 'dropdown',
options: THEME_OPTIONS,
};
export const MINI_MAP_PLACEMENT_OPTIONS = [
{ label: 'Right Bottom', value: MiniMapPlacement.rightBottom },
{ label: 'Right Top', value: MiniMapPlacement.rightTop },
{ label: 'Left Top', value: MiniMapPlacement.leftTop },
{ label: 'Left Bottom', value: MiniMapPlacement.leftBottom },
{ label: 'Hide', value: MiniMapPlacement.hide },
];
export const MINI_MAP_PLACEMENT: SettingsListItem = {
prop: 'minimapPlacement',
label: 'Minimap Placement',
type: 'dropdown',
options: MINI_MAP_PLACEMENT_OPTIONS,
};
export const PINGS_PLACEMENT_OPTIONS = [
{ label: 'Right Top', value: PingsPlacement.rightTop },
{ label: 'Left Top', value: PingsPlacement.leftTop },
{ label: 'Left Bottom', value: PingsPlacement.leftBottom },
{ label: 'Right Bottom', value: PingsPlacement.rightBottom },
];
export const PINGS_PLACEMENT: SettingsListItem = {
prop: 'pingsPlacement',
label: 'Pings Placement',
type: 'dropdown',
options: PINGS_PLACEMENT_OPTIONS,
};

View File

@@ -1,4 +1,4 @@
import { InterfaceStoredSettings } from '@/hooks/Mapper/mapRootProvider';
import { InterfaceStoredSettings } from '@/hooks/Mapper/mapRootProvider/types.ts';
export enum UserSettingsRemoteProps {
link_signature_on_splash = 'link_signature_on_splash',

View File

@@ -35,7 +35,7 @@ const itemTemplate = (item: CharacterTypeRaw & WithIsOwnCharacter, options: Virt
})}
style={{ height: options.props.itemSize + 'px' }}
>
<CharacterCard showCorporationLogo showAllyLogo showSystem showTicker {...item} />
<CharacterCard showCorporationLogo showAllyLogo showSystem showTicker showShip {...item} />
</div>
);
};

View File

@@ -1,6 +1,6 @@
import classes from './RightBar.module.scss';
import clsx from 'clsx';
import { useCallback } from 'react';
import { ReactNode, useCallback } from 'react';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper';
import { TooltipPosition } from '@/hooks/Mapper/components/ui-kit';
@@ -12,24 +12,21 @@ interface RightBarProps {
onShowOnTheMap?: () => void;
onShowMapSettings?: () => void;
onShowTrackingDialog?: () => void;
additionalContent?: ReactNode;
}
export const RightBar = ({ onShowOnTheMap, onShowMapSettings, onShowTrackingDialog }: RightBarProps) => {
export const RightBar = ({
onShowOnTheMap,
onShowMapSettings,
onShowTrackingDialog,
additionalContent,
}: RightBarProps) => {
const {
storedSettings: { interfaceSettings, setInterfaceSettings },
} = useMapRootState();
const canTrackCharacters = useMapCheckPermissions([UserPermission.TRACK_CHARACTER]);
const isShowMinimap = interfaceSettings.isShowMinimap === undefined ? true : interfaceSettings.isShowMinimap;
const toggleMinimap = useCallback(() => {
setInterfaceSettings(x => ({
...x,
isShowMinimap: !x.isShowMinimap,
}));
}, [setInterfaceSettings]);
const toggleKSpace = useCallback(() => {
setInterfaceSettings(x => ({
...x,
@@ -78,6 +75,7 @@ export const RightBar = ({ onShowOnTheMap, onShowMapSettings, onShowTrackingDial
</WdTooltipWrapper>
</>
)}
{additionalContent}
</div>
<div className="flex flex-col items-center mb-2 gap-1">
@@ -106,16 +104,6 @@ export const RightBar = ({ onShowOnTheMap, onShowMapSettings, onShowTrackingDial
</button>
</WdTooltipWrapper>
<WdTooltipWrapper content={isShowMinimap ? 'Hide minimap' : 'Show minimap'} 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={toggleMinimap}
>
<i className={isShowMinimap ? 'pi pi-eye' : 'pi pi-eye-slash'}></i>
</button>
</WdTooltipWrapper>
<WdTooltipWrapper content="Switch to menu" 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"

View File

@@ -67,8 +67,8 @@ export const SignatureSettings = ({ systemId, show, onHide, signatureData }: Map
if (values.type) {
const whShipSize = getWhSize(wormholes, values.type);
if (whShipSize) {
outCommand({
if (whShipSize !== undefined && whShipSize !== null) {
await outCommand({
type: OutCommand.updateConnectionShipSizeType,
data: {
source: systemId,

View File

@@ -1,5 +1,5 @@
import { Map, MAP_ROOT_ID } from '@/hooks/Mapper/components/map/Map.tsx';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { OutCommand, OutCommandHandler, SolarSystemConnection } from '@/hooks/Mapper/types';
import { MapRootData, useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { OnMapAddSystemCallback, OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
@@ -10,7 +10,6 @@ import {
SystemLinkSignatureDialog,
SystemSettingsDialog,
} 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';
@@ -27,26 +26,40 @@ import {
SearchOnSubmitCallback,
} from '@/hooks/Mapper/components/mapInterface/components/AddSystemDialog';
import { useHotkey } from '../../hooks/useHotkey';
import { STORED_INTERFACE_DEFAULT_VALUES } from '@/hooks/Mapper/mapRootProvider/constants.ts';
import { PingType } from '@/hooks/Mapper/types/ping.ts';
import { SystemPingDialog } from '@/hooks/Mapper/components/mapInterface/components/SystemPingDialog';
import { MiniMapPlacement } from '@/hooks/Mapper/mapRootProvider/types.ts';
import { MINIMAP_PLACEMENT_MAP } from '@/hooks/Mapper/constants.ts';
import type { PanelPosition } from '@reactflow/core';
import { MINI_MAP_PLACEMENT_OFFSETS } from './constants.ts';
// TODO: INFO - this component needs for abstract work with Map instance
export const MapWrapper = () => {
const {
update,
outCommand,
data: { selectedConnections, selectedSystems, hubs, userHubs, systems, linkSignatureToSystem, systemSignatures },
data: {
pings,
selectedConnections,
selectedSystems,
hubs,
userHubs,
systems,
linkSignatureToSystem,
systemSignatures,
},
storedSettings: { interfaceSettings },
} = useMapRootState();
const {
isShowMenu,
isShowMinimap = STORED_INTERFACE_DEFAULT_VALUES.isShowMinimap,
isShowKSpace,
isThickConnections,
isShowBackgroundPattern,
isShowUnsplashedSignatures,
isSoftBackground,
theme,
minimapPlacement,
} = interfaceSettings;
const { deleteSystems } = useDeleteSystems();
@@ -58,6 +71,7 @@ export const MapWrapper = () => {
const { handleSystemMultipleContext, ...systemMultipleCtxProps } = useContextMenuSystemMultipleHandlers();
const [openSettings, setOpenSettings] = useState<string | null>(null);
const [openPing, setOpenPing] = useState<{ type: PingType; solar_system_id: string } | null>(null);
const [openCustomLabel, setOpenCustomLabel] = useState<string | null>(null);
const [openAddSystem, setOpenAddSystem] = useState<XYPosition | null>(null);
const [selectedConnection, setSelectedConnection] = useState<SolarSystemConnection | null>(null);
@@ -99,6 +113,8 @@ export const MapWrapper = () => {
event => {
switch (event.type) {
case OutCommand.openSettings:
// TODO - need fix it
// @ts-ignore
setOpenSettings(event.data.system_id);
break;
default:
@@ -111,6 +127,7 @@ export const MapWrapper = () => {
);
const handleSystemContextMenu = useCallback(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(ev: any, systemId: string) => {
const { selectedSystems, systems } = ref.current;
if (selectedSystems.length > 1) {
@@ -130,11 +147,13 @@ export const MapWrapper = () => {
const handleDeleteSelected = useCallback(() => {
const restDel = getNodes()
.filter(x => x.selected && !x.data.locked)
.filter(x => !pings.some(p => x.data.id === p.solar_system_id))
.map(x => x.data.id);
if (restDel.length > 0) {
ref.current.deleteSystems(restDel);
}
}, [getNodes]);
}, [getNodes, pings]);
const onAddSystem: OnMapAddSystemCallback = useCallback(({ coordinates }) => {
setOpenAddSystem(coordinates);
@@ -158,6 +177,27 @@ export const MapWrapper = () => {
[openAddSystem, outCommand],
);
const handleOpenSettings = useCallback(() => {
ref.current.systemContextProps.systemId && setOpenSettings(ref.current.systemContextProps.systemId);
}, []);
const handleTogglePing = useCallback(async (type: PingType, solar_system_id: string, hasPing: boolean) => {
if (hasPing) {
await outCommand({
type: OutCommand.cancelPing,
data: { type, solar_system_id: solar_system_id },
});
return;
}
setOpenPing({ type, solar_system_id });
}, []);
const handleCustomLabelDialog = useCallback(() => {
const { systemContextProps } = ref.current;
systemContextProps.systemId && setOpenCustomLabel(systemContextProps.systemId);
}, []);
useHotkey(false, ['Delete'], (event: KeyboardEvent) => {
const targetWindow = (event.target as HTMLHtmlElement)?.closest(`[data-window-id="${MAP_ROOT_ID}"]`);
@@ -179,6 +219,22 @@ export const MapWrapper = () => {
outCommand({ type: OutCommand.loadSignatures, data: {} });
}, [isShowUnsplashedSignatures, systems]);
const { showMinimap, minimapPosition, minimapClasses } = useMemo(() => {
const rawPlacement = minimapPlacement == null ? MiniMapPlacement.rightBottom : minimapPlacement;
if (rawPlacement === MiniMapPlacement.hide) {
return { minimapPosition: undefined, showMinimap: false, minimapClasses: '' };
}
const mmClasses = MINI_MAP_PLACEMENT_OFFSETS[rawPlacement];
return {
minimapPosition: MINIMAP_PLACEMENT_MAP[rawPlacement] as PanelPosition,
showMinimap: true,
minimapClasses: isShowMenu ? mmClasses.default : mmClasses.withLeftMenu,
};
}, [minimapPlacement, isShowMenu]);
return (
<>
<Map
@@ -188,19 +244,29 @@ export const MapWrapper = () => {
onConnectionInfoClick={handleConnectionDbClick}
onSystemContextMenu={handleSystemContextMenu}
onSelectionContextMenu={handleSystemMultipleContext}
minimapClasses={!isShowMenu ? classes.MiniMap : undefined}
isShowMinimap={isShowMinimap}
minimapClasses={minimapClasses}
isShowMinimap={showMinimap}
showKSpaceBG={isShowKSpace}
isThickConnections={isThickConnections}
isShowBackgroundPattern={isShowBackgroundPattern}
isSoftBackground={isSoftBackground}
theme={theme}
pings={pings}
onAddSystem={onAddSystem}
minimapPlacement={minimapPosition}
/>
{openSettings != null && (
<SystemSettingsDialog systemId={openSettings} visible setVisible={() => setOpenSettings(null)} />
)}
{openPing != null && (
<SystemPingDialog
systemId={openPing.solar_system_id}
type={openPing.type}
visible
setVisible={() => setOpenPing(null)}
/>
)}
{openCustomLabel != null && (
<SystemCustomLabelDialog systemId={openCustomLabel} visible setVisible={() => setOpenCustomLabel(null)} />
@@ -223,13 +289,9 @@ export const MapWrapper = () => {
hubs={hubs}
userHubs={userHubs}
{...systemContextProps}
onOpenSettings={() => {
systemContextProps.systemId && setOpenSettings(systemContextProps.systemId);
}}
onCustomLabelDialog={() => {
const { systemContextProps } = ref.current;
systemContextProps.systemId && setOpenCustomLabel(systemContextProps.systemId);
}}
onOpenSettings={handleOpenSettings}
onTogglePing={handleTogglePing}
onCustomLabelDialog={handleCustomLabelDialog}
/>
<ContextMenuSystemMultiple {...systemMultipleCtxProps} />

View File

@@ -0,0 +1,8 @@
import { MiniMapPlacement } from '@/hooks/Mapper/mapRootProvider/types.ts';
export const MINI_MAP_PLACEMENT_OFFSETS = {
[MiniMapPlacement.rightTop]: { default: '!top-[48px]', withLeftMenu: '!top-[48px] !right-[58px]' },
[MiniMapPlacement.rightBottom]: { default: '!bottom-[0px]', withLeftMenu: '!bottom-[0px] !right-[58px]' },
[MiniMapPlacement.leftTop]: { default: '!top-[48px] !left-[56px]', withLeftMenu: '!top-[48px] !left-[56px]' },
[MiniMapPlacement.leftBottom]: { default: '!left-[56px] !bottom-[0px]', withLeftMenu: '!left-[56px] !bottom-[0px]' },
};

View File

@@ -1,7 +1,8 @@
import { MutableRefObject, useCallback, useEffect, useRef } from 'react';
import { Command, Commands, MapHandlers } from '@/hooks/Mapper/types';
import { MapEvent } from '@/hooks/Mapper/events';
// import { useThrottle } from '@/hooks/Mapper/hooks';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { Command, Commands, MapHandlers } from '@/hooks/Mapper/types';
import { MutableRefObject, useCallback, useEffect, useRef } from 'react';
export const useCommonMapEventProcessor = () => {
const mapRef = useRef<MapHandlers>() as MutableRefObject<MapHandlers>;
@@ -11,13 +12,14 @@ export const useCommonMapEventProcessor = () => {
const refQueue = useRef<MapEvent<Command>[]>([]);
// const ref = useRef({})
const runCommand = useCallback(({ name, data }: MapEvent<Command>) => {
switch (name) {
case Commands.addSystems:
case Commands.removeSystems:
// case Commands.updateSystems:
// case Commands.addConnections:
// case Commands.removeConnections:
// case Commands.updateConnection:
refQueue.current.push({ name, data });
return;
}
@@ -26,9 +28,17 @@ export const useCommonMapEventProcessor = () => {
mapRef.current?.command(name, data);
}, []);
useEffect(() => {
refQueue.current.forEach(x => mapRef.current?.command(x.name, x.data));
const processQueue = useCallback(() => {
const commands = [...refQueue.current];
refQueue.current = [];
commands.forEach(x => mapRef.current?.command(x.name, x.data));
}, []);
// const throttledProcessQueue = useThrottle(processQueue, 200);
useEffect(() => {
// throttledProcessQueue();
processQueue();
}, [systems]);
return {

View File

@@ -1,9 +1,9 @@
import { Characters } from '../characters/Characters';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useMemo } from 'react';
import clsx from 'clsx';
import { sortOnlineFunc } from '@/hooks/Mapper/components/hooks/useGetOwnOnlineCharacters.ts';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
import clsx from 'clsx';
import { useMemo } from 'react';
import { Characters } from '../characters/Characters';
const Topbar = ({ children }: WithChildren) => {
const {
@@ -24,7 +24,10 @@ const Topbar = ({ children }: WithChildren) => {
>
<span className="flex-1"></span>
<span className="mr-2"></span>
<Characters data={charsToShow} />
<div className="flex gap-1 items-center">
<Characters data={charsToShow} />
</div>
{children}
</nav>
);

View File

@@ -1,9 +1,3 @@
import { useCallback } from 'react';
import clsx from 'clsx';
import { SystemView } from '@/hooks/Mapper/components/ui-kit/SystemView';
import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types';
import { Commands } from '@/hooks/Mapper/types/mapHandlers';
import { emitMapEvent } from '@/hooks/Mapper/events';
import {
TooltipPosition,
WdEveEntityPortrait,
@@ -11,19 +5,30 @@ import {
WdEveEntityPortraitType,
WdTooltipWrapper,
} from '@/hooks/Mapper/components/ui-kit';
import { SystemView } from '@/hooks/Mapper/components/ui-kit/SystemView';
import { emitMapEvent } from '@/hooks/Mapper/events';
import { isDocked } from '@/hooks/Mapper/helpers/isDocked.ts';
import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types';
import { WithClassName } from '@/hooks/Mapper/types/common.ts';
import { Commands } from '@/hooks/Mapper/types/mapHandlers';
import clsx from 'clsx';
import { useCallback } from 'react';
import classes from './CharacterCard.module.scss';
type CharacterCardProps = {
export type CharacterCardProps = {
compact?: boolean;
showSystem?: boolean;
showTicker?: boolean;
showShip?: boolean;
showShipName?: boolean;
useSystemsCache?: boolean;
showCorporationLogo?: boolean;
showAllyLogo?: boolean;
} & CharacterTypeRaw &
WithIsOwnCharacter;
simpleMode?: boolean;
} & WithIsOwnCharacter &
WithClassName;
type CharacterCardInnerProps = CharacterCardProps & CharacterTypeRaw;
const SHIP_NAME_RX = /u'|'/g;
export const getShipName = (name: string) => {
@@ -34,16 +39,19 @@ export const getShipName = (name: string) => {
};
export const CharacterCard = ({
simpleMode,
compact = false,
isOwn,
showSystem,
showShip,
showShipName,
showCorporationLogo,
showAllyLogo,
showTicker,
useSystemsCache,
className,
...char
}: CharacterCardProps) => {
}: CharacterCardInnerProps) => {
const handleSelect = useCallback(() => {
emitMapEvent({
name: Commands.centerSystem,
@@ -56,9 +64,55 @@ export const CharacterCard = ({
const shipType = char.ship?.ship_type_info?.name;
const locationShown = showSystem && char.location?.solar_system_id;
// INFO: Simple mode show only name and icon of ally/corp. By default it compact view
if (simpleMode) {
return (
<div className={clsx('text-xs box-border', className)} onClick={handleSelect}>
<div className="flex items-center gap-1 relative">
<WdEveEntityPortrait eveId={char.eve_id} size={WdEveEntityPortraitSize.w18} />
{!char.alliance_id && (
<WdTooltipWrapper position={TooltipPosition.top} content={char.corporation_name}>
<WdEveEntityPortrait
type={WdEveEntityPortraitType.corporation}
eveId={char.corporation_id?.toString()}
size={WdEveEntityPortraitSize.w18}
/>
</WdTooltipWrapper>
)}
{char.alliance_id && (
<WdTooltipWrapper position={TooltipPosition.top} content={char.alliance_name}>
<WdEveEntityPortrait
type={WdEveEntityPortraitType.alliance}
eveId={char.alliance_id?.toString()}
size={WdEveEntityPortraitSize.w18}
/>
</WdTooltipWrapper>
)}
<div className="flex overflow-hidden text-left">
<div className="flex">
<span
className={clsx(
'overflow-hidden text-ellipsis whitespace-nowrap',
isOwn ? 'text-orange-400' : 'text-gray-200',
)}
title={char.name}
>
{char.name}
</span>
{showTicker && <span className="flex-shrink-0 text-gray-400 ml-1">[{tickerText}]</span>}
</div>
</div>
</div>
</div>
);
}
if (compact) {
return (
<div className="text-xs box-border w-full" onClick={handleSelect}>
<div className={clsx('text-xs box-border w-full', className)} onClick={handleSelect}>
<div className="w-full flex items-center gap-1 relative">
<WdEveEntityPortrait eveId={char.eve_id} size={WdEveEntityPortraitSize.w18} />
@@ -66,7 +120,7 @@ export const CharacterCard = ({
<WdTooltipWrapper position={TooltipPosition.top} content={char.corporation_name}>
<WdEveEntityPortrait
type={WdEveEntityPortraitType.corporation}
eveId={char.corporation_id.toString()}
eveId={char.corporation_id?.toString()}
size={WdEveEntityPortraitSize.w18}
/>
</WdTooltipWrapper>
@@ -76,7 +130,7 @@ export const CharacterCard = ({
<WdTooltipWrapper position={TooltipPosition.top} content={char.alliance_name}>
<WdEveEntityPortrait
type={WdEveEntityPortraitType.alliance}
eveId={char.alliance_id.toString()}
eveId={char.alliance_id?.toString()}
size={WdEveEntityPortraitSize.w18}
/>
</WdTooltipWrapper>
@@ -98,7 +152,7 @@ export const CharacterCard = ({
</div>
</div>
{shipType && (
{showShip && shipType && (
<>
{!showShipName && (
<div
@@ -123,10 +177,10 @@ export const CharacterCard = ({
</div>
)}
{char.ship && (
<WdTooltipWrapper position={TooltipPosition.top} content={char.ship.ship_type_info.name}>
<WdTooltipWrapper position={TooltipPosition.top} content={char.ship.ship_type_info?.name}>
<WdEveEntityPortrait
type={WdEveEntityPortraitType.ship}
eveId={char.ship.ship_type_id.toString()}
eveId={char.ship.ship_type_id?.toString()}
size={WdEveEntityPortraitSize.w18}
/>
</WdTooltipWrapper>
@@ -148,7 +202,7 @@ export const CharacterCard = ({
<WdTooltipWrapper position={TooltipPosition.top} content={char.corporation_name}>
<WdEveEntityPortrait
type={WdEveEntityPortraitType.corporation}
eveId={char.corporation_id.toString()}
eveId={char.corporation_id?.toString()}
size={WdEveEntityPortraitSize.w33}
/>
</WdTooltipWrapper>
@@ -158,7 +212,7 @@ export const CharacterCard = ({
<WdTooltipWrapper position={TooltipPosition.top} content={char.alliance_name}>
<WdEveEntityPortrait
type={WdEveEntityPortraitType.alliance}
eveId={char.alliance_id.toString()}
eveId={char.alliance_id?.toString()}
size={WdEveEntityPortraitSize.w33}
/>
</WdTooltipWrapper>
@@ -192,7 +246,7 @@ export const CharacterCard = ({
)
)}
</div>
{shipType && (
{showShip && shipType && (
<>
<div className="flex flex-col flex-shrink-0 items-end self-start">
<div
@@ -212,7 +266,7 @@ export const CharacterCard = ({
{char.ship && (
<WdEveEntityPortrait
type={WdEveEntityPortraitType.ship}
eveId={char.ship.ship_type_id.toString()}
eveId={char.ship.ship_type_id?.toString()}
size={WdEveEntityPortraitSize.w33}
/>
)}

View File

@@ -0,0 +1,23 @@
import { CharacterCard, CharacterCardProps } from '@/hooks/Mapper/components/ui-kit/CharacterCard';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useMemo } from 'react';
type CharacterCardByIdProps = {
characterId: string;
} & Omit<CharacterCardProps, 'isOwn'>;
export const CharacterCardById = ({ characterId, ...props }: CharacterCardByIdProps) => {
const {
data: { characters },
} = useMapRootState();
const charInfo = useMemo(() => {
return characters.find(x => x.eve_id === characterId);
}, [characterId, characters]);
if (!charInfo) {
return 'No character found.';
}
return <CharacterCard isOwn={false} {...charInfo} {...props} />;
};

View File

@@ -0,0 +1 @@
export * from './CharacterCardById';

View File

@@ -0,0 +1,11 @@
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import remarkBreaks from 'remark-breaks';
const REMARK_PLUGINS = [remarkGfm, remarkBreaks];
type MarkdownTextViewerProps = { children: string };
export const MarkdownTextViewer = ({ children }: MarkdownTextViewerProps) => {
return <Markdown remarkPlugins={REMARK_PLUGINS}>{children}</Markdown>;
};

View File

@@ -0,0 +1,21 @@
import { ReactNode } from 'react';
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper';
import { TooltipPosition } from '@/hooks/Mapper/components/ui-kit/WdTooltip';
import clsx from 'clsx';
type MenuItemWithInfoProps = { infoTitle: ReactNode; infoClass?: string } & WithChildren;
export const MenuItemWithInfo = ({ children, infoClass, infoTitle }: MenuItemWithInfoProps) => {
return (
<div className="flex justify-between w-full h-full items-center">
{children}
<WdTooltipWrapper
content={infoTitle}
position={TooltipPosition.top}
className="!opacity-100 !pointer-events-auto"
>
<div className={clsx('pi text-orange-400', infoClass)} />
</WdTooltipWrapper>
</div>
);
};

View File

@@ -1,5 +1,4 @@
import { WithClassName } from '@/hooks/Mapper/types/common.ts';
import { SystemViewStandalone } from '@/hooks/Mapper/components/ui-kit';
import { SystemViewStandalone, SystemViewStandaloneProps } from '@/hooks/Mapper/components/ui-kit';
import { useLoadSystemStatic } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts';
import { useMemo } from 'react';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
@@ -8,18 +7,11 @@ import { SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types';
export type SystemViewProps = {
systemId: string;
systemInfo?: SolarSystemStaticInfoRaw;
hideRegion?: boolean;
useSystemsCache?: boolean;
showCustomName?: boolean;
} & WithClassName;
} & Pick<SystemViewStandaloneProps, 'className' | 'compact' | 'hideRegion'>;
export const SystemView = ({
systemId,
systemInfo: customSystemInfo,
hideRegion,
className,
showCustomName,
}: SystemViewProps) => {
export const SystemView = ({ systemId, systemInfo: customSystemInfo, showCustomName, ...rest }: SystemViewProps) => {
const memSystems = useMemo(() => [systemId], [systemId]);
const { systems, loading } = useLoadSystemStatic({ systems: memSystems });
@@ -47,13 +39,8 @@ export const SystemView = ({
}
if (!mapSystemInfo) {
return <SystemViewStandalone hideRegion={hideRegion} className={className} {...systemInfo} />;
return <SystemViewStandalone {...rest} {...systemInfo} />;
}
return (
<div>
<SystemViewStandalone hideRegion={hideRegion} className={className} {...systemInfo} />
<span>{systemInfo.solar_system_name}</span>
</div>
);
return <SystemViewStandalone customName={mapSystemInfo.name ?? undefined} {...rest} {...systemInfo} />;
};

View File

@@ -1,10 +1,11 @@
import { useEffect, useState, useRef } from 'react';
import { WithClassName } from '@/hooks/Mapper/types/common.ts';
interface TimeAgoProps {
timestamp: string; // Теперь тип string, так как приходит ISO 8601 строка
}
export const TimeAgo = ({ timestamp }: TimeAgoProps) => {
export const TimeAgo = ({ timestamp, className }: TimeAgoProps & WithClassName) => {
const [timeAgo, setTimeAgo] = useState<string>('');
const timeoutIdRef = useRef<number | null>(null);
@@ -64,5 +65,5 @@ export const TimeAgo = ({ timestamp }: TimeAgoProps) => {
return `${days} days ago`;
};
return <span>{timeAgo}</span>;
return <span className={className}>{timeAgo}</span>;
};

View File

@@ -11,12 +11,14 @@ export enum WdImageSize {
large = 'large',
}
export type WdImgButtonTooltip = Pick<WdTooltipWrapperProps, 'content' | 'position' | 'offset' | 'className'>;
export type WdImgButtonProps = {
onClick?(e: MouseEvent): void;
source?: string;
width?: number;
height?: number;
tooltip?: Pick<WdTooltipWrapperProps, 'content' | 'position' | 'offset' | 'className'>;
tooltip?: WdImgButtonTooltip;
textSize?: WdImageSize;
} & WithClassName &
HTMLProps<HTMLDivElement>;

View File

@@ -0,0 +1,16 @@
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
import clsx from 'clsx';
type WdMenuItemProps = { icon?: string; disabled?: boolean } & WithChildren;
export const WdMenuItem = ({ children, icon, disabled }: WdMenuItemProps) => {
return (
<a
className={clsx('flex gap-[6px] w-full h-full items-center px-[12px] !py-0 ml-[-2px]', 'p-menuitem-link', {
'p-disabled': disabled,
})}
>
{icon && <div className={clsx('min-w-[20px]', icon)}></div>}
<div className="w-full">{children}</div>
</a>
);
};

View File

@@ -1,4 +1,5 @@
export * from './CharacterCard';
export * from './CharacterCardById';
export * from './InfoDrawer';
export * from './FixedTooltip';
export * from './LayoutEventBlocker';
@@ -17,3 +18,6 @@ export * from './WdRadioButton';
export * from './WdEveEntityPortrait';
export * from './WdTransition';
export * from './LoadingWrapper';
export * from './WdMenuItem';
export * from './MenuItemWithInfo';
export * from './MarkdownTextViewer.tsx';

View File

@@ -1,3 +1,5 @@
import { PingsPlacement } from '@/hooks/Mapper/mapRootProvider/types.ts';
export enum SESSION_KEY {
viewPort = 'viewPort',
windows = 'windows',
@@ -139,3 +141,10 @@ export const K162_TYPES_MAP: { [key: string]: K162Type } = K162_TYPES.reduce(
(acc, x) => ({ ...acc, [x.value]: x }),
{},
);
export const MINIMAP_PLACEMENT_MAP = {
[PingsPlacement.rightTop]: 'top-right',
[PingsPlacement.leftTop]: 'top-left',
[PingsPlacement.rightBottom]: 'bottom-right',
[PingsPlacement.leftBottom]: 'bottom-left',
};

View File

@@ -1,5 +1,10 @@
import {
MAPPING_GROUP_TO_ENG,
MAPPING_TYPE_TO_ENG,
} from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
import { SignatureGroup, SignatureKind, SystemSignature } from '@/hooks/Mapper/types';
import { MAPPING_TYPE_TO_ENG } from '@/hooks/Mapper/components/mapInterface/widgets/SystemSignatures/constants.ts';
export const UNKNOWN_SIGNATURE_NAME = 'Unknown';
export const parseSignatures = (value: string, availableKeys: string[]): SystemSignature[] => {
const outArr: SystemSignature[] = [];
@@ -14,13 +19,39 @@ export const parseSignatures = (value: string, availableKeys: string[]): SystemS
continue;
}
const kind = MAPPING_TYPE_TO_ENG[sigArrInfo[1] as SignatureKind];
// Extract the signature ID and check if it's valid (XXX-XXX format)
const sigId = sigArrInfo[0];
if (!sigId || !sigId.match(/^[A-Z]{3}-\d{3}$/)) {
continue;
}
// Try to map the kind, or fall back to CosmicSignature if unknown
const typeString = sigArrInfo[1];
let kind = SignatureKind.CosmicSignature;
// Try to map the kind using the flattened mapping
const mappedKind = MAPPING_TYPE_TO_ENG[typeString];
if (mappedKind && availableKeys.includes(mappedKind)) {
kind = mappedKind;
}
// Try to map the group, or fall back to CosmicSignature if unknown
const rawGroup = sigArrInfo[2];
let group = SignatureGroup.CosmicSignature;
// Try to map the group using the flattened mapping
const mappedGroup = MAPPING_GROUP_TO_ENG[rawGroup];
if (mappedGroup) {
group = mappedGroup;
}
const signature: SystemSignature = {
eve_id: sigArrInfo[0],
kind: availableKeys.includes(kind) ? kind : SignatureKind.CosmicSignature,
group: sigArrInfo[2] as SignatureGroup,
name: sigArrInfo[3],
eve_id: sigId,
kind,
group,
name: sigArrInfo[3] || UNKNOWN_SIGNATURE_NAME,
type: '',
};

View File

@@ -1,5 +1,6 @@
export * from './usePageVisibility';
export * from './useActualizeSettings';
export * from './useClipboard';
export * from './useHotkey';
export * from './usePageVisibility';
export * from './useSkipContextMenu';
export * from './useActualizeSettings';
export * from './useThrottle';

View File

@@ -0,0 +1,13 @@
import { useCallback, useRef } from 'react';
export const useThrottle = (callback: any, limit: number) => {
const lastCallRef = useRef(0);
const throttledCallback = useCallback(() => {
const now = Date.now();
if (now - lastCallRef.current >= limit) {
lastCallRef.current = now;
callback();
}
}, [callback, limit]);
return throttledCallback;
};

View File

@@ -22,6 +22,7 @@ import { DetailedKill } from '../types/kills';
import { InterfaceStoredSettings, RoutesType } from '@/hooks/Mapper/mapRootProvider/types.ts';
import { DEFAULT_ROUTES_SETTINGS, STORED_INTERFACE_DEFAULT_VALUES } from '@/hooks/Mapper/mapRootProvider/constants.ts';
import { useMapUserSettings } from '@/hooks/Mapper/mapRootProvider/hooks/useMapUserSettings.ts';
import { useGlobalHooks } from '@/hooks/Mapper/mapRootProvider/hooks/useGlobalHooks.ts';
export type MapRootData = MapUnionTypes & {
selectedSystems: string[];
@@ -34,6 +35,7 @@ export type MapRootData = MapUnionTypes & {
loading?: boolean;
};
trackingCharactersData: TrackingCharacter[];
loadingPublicRoutes: boolean;
};
const INITIAL_DATA: MapRootData = {
@@ -66,11 +68,12 @@ const INITIAL_DATA: MapRootData = {
linkSignatureToSystem: null,
mainCharacterEveId: null,
followingCharacterEveId: null,
pings: [],
loadingPublicRoutes: false,
};
export enum InterfaceStoredSettingsProps {
isShowMenu = 'isShowMenu',
isShowMinimap = 'isShowMinimap',
isShowKSpace = 'isShowKSpace',
isThickConnections = 'isThickConnections',
isShowUnsplashedSignatures = 'isShowUnsplashedSignatures',
@@ -143,6 +146,7 @@ type MapRootProviderProps = {
// eslint-disable-next-line react/display-name
const MapRootHandlers = forwardRef(({ children }: WithChildren, fwdRef: ForwardedRef<any>) => {
useMapRootHandlers(fwdRef);
useGlobalHooks();
return <>{children}</>;
});

View File

@@ -1,14 +1,21 @@
import { AvailableThemes, InterfaceStoredSettings, RoutesType } from '@/hooks/Mapper/mapRootProvider/types.ts';
import {
AvailableThemes,
InterfaceStoredSettings,
MiniMapPlacement,
PingsPlacement,
RoutesType,
} from '@/hooks/Mapper/mapRootProvider/types.ts';
export const STORED_INTERFACE_DEFAULT_VALUES: InterfaceStoredSettings = {
isShowMenu: false,
isShowMinimap: true,
isShowKSpace: false,
isThickConnections: false,
isShowUnsplashedSignatures: false,
isShowBackgroundPattern: true,
isSoftBackground: false,
theme: AvailableThemes.default,
pingsPlacement: PingsPlacement.rightTop,
minimapPlacement: MiniMapPlacement.rightBottom,
};
export const DEFAULT_ROUTES_SETTINGS: RoutesType = {

View File

@@ -9,3 +9,4 @@ export * from './useCommandsCharacters';
export * from './useCommandComments';
export * from './useGetCacheCharacter';
export * from './useCommandsActivity';
export * from './useCommandPings';

View File

@@ -0,0 +1,23 @@
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { CommandPingAdded, CommandPingCancelled } from '@/hooks/Mapper/types';
import { useCallback, useRef } from 'react';
export const useCommandPings = () => {
const {
update,
data: { pings },
} = useMapRootState();
const ref = useRef({ update, pings });
ref.current = { update, pings };
const pingAdded = useCallback((pings: CommandPingAdded) => {
ref.current.update({ pings });
}, []);
const pingCancelled = useCallback(({ type, solar_system_id }: CommandPingCancelled) => {
const newPings = ref.current.pings.filter(x => x.solar_system_id !== solar_system_id && x.type !== type);
ref.current.update({ pings: newPings });
}, []);
return { pingAdded, pingCancelled };
};

View File

@@ -70,6 +70,9 @@ export const useCommandsSystems = () => {
const updateSystemSignatures = useCallback(
async (systemId: string) => {
const { update, systemSignatures } = ref.current;
// TODO need to fix it
// @ts-ignore
const { signatures } = await outCommand({
type: OutCommand.getSignatures,
data: { system_id: `${systemId}` },
@@ -80,7 +83,7 @@ export const useCommandsSystems = () => {
[outCommand],
);
const updateLinkSignatureToSystem = useCallback(async (command: CommandLinkSignatureToSystem) => {
const updateLinkSignatureToSystem = useCallback(async (command: CommandLinkSignatureToSystem | null) => {
const { update } = ref.current;
update({ linkSignatureToSystem: command }, true);
}, []);

View File

@@ -0,0 +1,6 @@
import { useLoadPublicRoutes } from './useLoadPublicRoutes';
/* TODO this hook needs for call some actions which should affect all mapper*/
export const useGlobalHooks = () => {
useLoadPublicRoutes();
};

View File

@@ -0,0 +1,46 @@
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { LoadRoutesCommand } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/types.ts';
import { useCallback, useEffect } from 'react';
import { Commands, OutCommand } from '@/hooks/Mapper/types';
import { useLoadRoutes } from '@/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/hooks';
import { useMapEventListener } from '@/hooks/Mapper/events';
export const useLoadPublicRoutes = () => {
const {
outCommand,
storedSettings: { settingsRoutes },
data: { hubs, routes, pings },
update,
} = useMapRootState();
const loadRoutesCommand: LoadRoutesCommand = useCallback(
async (systemId, routesSettings) => {
outCommand({
type: OutCommand.getRoutes,
data: {
system_id: systemId,
routes_settings: routesSettings,
},
});
},
[outCommand],
);
const { loading, setLoading } = useLoadRoutes({
data: settingsRoutes,
hubs: hubs,
loadRoutesCommand,
routesList: routes,
deps: [pings],
});
useEffect(() => {
update({ loadingPublicRoutes: loading });
}, [loading, update]);
useMapEventListener(event => {
if (event.name === Commands.routes) {
setLoading(false);
}
});
};

View File

@@ -23,10 +23,13 @@ import {
Commands,
MapHandlers,
CommandCommentRemoved,
CommandPingAdded,
CommandPingCancelled,
} from '@/hooks/Mapper/types/mapHandlers.ts';
import {
useCommandComments,
useCommandPings,
useCommandsCharacters,
useCommandsConnections,
useCommandsSystems,
@@ -57,6 +60,7 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
const mapRoutes = useRoutes();
const mapUserRoutes = useUserRoutes();
const { addComment, removeComment } = useCommandComments();
const { pingAdded, pingCancelled } = useCommandPings();
const { characterActivityData, trackingCharactersData, userSettingsUpdated } = useCommandsActivity();
useImperativeHandle(
@@ -163,6 +167,14 @@ export const useMapRootHandlers = (ref: ForwardedRef<MapHandlers>) => {
removeComment(data as CommandCommentRemoved);
break;
case Commands.pingAdded:
pingAdded(data as CommandPingAdded);
break;
case Commands.pingCancelled:
pingCancelled(data as CommandPingCancelled);
break;
default:
console.warn(`JOipP Interface handlers: Unknown command: ${type}`, data);
break;

View File

@@ -8,7 +8,7 @@ import {
} from '@/hooks/Mapper/components/mapInterface/constants.tsx';
import { WindowProps } from '@/hooks/Mapper/components/ui-kit/WindowManager/types.ts';
import { useCallback, useEffect, useRef } from 'react';
import { SNAP_GAP, WindowsManagerOnChange } from '@/hooks/Mapper/components/ui-kit/WindowManager';
import { /*SNAP_GAP,*/ WindowsManagerOnChange } from '@/hooks/Mapper/components/ui-kit/WindowManager';
export type StoredWindowProps = Omit<WindowProps, 'content'>;
export type WindowStoreInfo = {
@@ -17,7 +17,7 @@ export type WindowStoreInfo = {
visible: WidgetsIds[];
viewPort?: { w: number; h: number } | undefined;
};
export type UpdateWidgetSettingsFunc = (widgets: WindowProps[]) => void;
// export type UpdateWidgetSettingsFunc = (widgets: WindowProps[]) => void;
export type ToggleWidgetVisibility = (widgetId: WidgetsIds) => void;
export const getDefaultWidgetProps = () => ({
@@ -66,7 +66,7 @@ export const useStoreWidgets = () => {
...x,
windows: windows.map(wnd => {
if (wnd.id === widgetId) {
return { ...wnd, position: { x: SNAP_GAP, y: SNAP_GAP }, zIndex: maxZIndex + 1 };
return { ...wnd, /*position: { x: SNAP_GAP, y: SNAP_GAP },*/ zIndex: maxZIndex + 1 };
}
return wnd;

View File

@@ -3,15 +3,31 @@ export enum AvailableThemes {
pathfinder = 'pathfinder',
}
export enum MiniMapPlacement {
rightTop = 'rightTop',
rightBottom = 'rightBottom',
leftTop = 'leftTop',
leftBottom = 'leftBottom',
hide = 'hide',
}
export enum PingsPlacement {
rightTop = 'rightTop',
rightBottom = 'rightBottom',
leftTop = 'leftTop',
leftBottom = 'leftBottom',
}
export type InterfaceStoredSettings = {
isShowMenu: boolean;
isShowMinimap: boolean;
isShowKSpace: boolean;
isThickConnections: boolean;
isShowUnsplashedSignatures: boolean;
isShowBackgroundPattern: boolean;
isSoftBackground: boolean;
theme: AvailableThemes;
minimapPlacement: MiniMapPlacement;
pingsPlacement: PingsPlacement;
};
export type RoutesType = {

View File

@@ -33,6 +33,7 @@ export type CharacterTypeRaw = {
corporation_id: number;
corporation_name: string;
corporation_ticker: string;
tracking_paused: boolean;
};
export interface TrackingCharacter {

View File

@@ -8,3 +8,4 @@ export * from './signatures';
export * from './connectionPassages';
export * from './permissions';
export * from './comment';
export * from './ping';

View File

@@ -1,10 +1,10 @@
import { SolarSystemRawType, SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types/system.ts';
import { SolarSystemConnection } from '@/hooks/Mapper/types/connection.ts';
import { WormholeDataRaw } from '@/hooks/Mapper/types/wormholes.ts';
import { CommentType, PingData, SystemSignature, UserPermissions } from '@/hooks/Mapper/types';
import { ActivitySummary, CharacterTypeRaw, TrackingCharacter } from '@/hooks/Mapper/types/character.ts';
import { RoutesList } from '@/hooks/Mapper/types/routes.ts';
import { SolarSystemConnection } from '@/hooks/Mapper/types/connection.ts';
import { DetailedKill, Kill } from '@/hooks/Mapper/types/kills.ts';
import { CommentType, SystemSignature, UserPermissions } from '@/hooks/Mapper/types';
import { RoutesList } from '@/hooks/Mapper/types/routes.ts';
import { SolarSystemRawType, SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types/system.ts';
import { WormholeDataRaw } from '@/hooks/Mapper/types/wormholes.ts';
export enum Commands {
init = 'init',
@@ -37,6 +37,8 @@ export enum Commands {
updateTracking = 'update_tracking',
userSettingsUpdated = 'user_settings_updated',
showTracking = 'show_tracking',
pingAdded = 'ping_added',
pingCancelled = 'ping_cancelled',
}
export type Command =
@@ -69,7 +71,9 @@ export type Command =
| Commands.userSettingsUpdated
| Commands.updateActivity
| Commands.updateTracking
| Commands.showTracking;
| Commands.showTracking
| Commands.pingAdded
| Commands.pingCancelled;
export type CommandInit = {
systems: SolarSystemRawType[];
@@ -78,6 +82,8 @@ export type CommandInit = {
system_static_infos: SolarSystemStaticInfoRaw[];
connections: SolarSystemConnection[];
wormholes: WormholeDataRaw[];
// TODO WHY HERE ANY?!!?!?
effects: any[];
characters: CharacterTypeRaw[];
present_characters: string[];
@@ -143,6 +149,8 @@ export type CommandUpdateTracking = {
track: boolean;
follow: boolean;
};
export type CommandPingAdded = PingData[];
export type CommandPingCancelled = Pick<PingData, 'type' | 'solar_system_id'>;
export interface UserSettings {
primaryCharacterId?: string;
@@ -190,6 +198,8 @@ export interface CommandData {
[Commands.systemCommentRemoved]: CommandCommentRemoved;
[Commands.systemCommentsUpdated]: unknown;
[Commands.showTracking]: CommandShowTracking;
[Commands.pingAdded]: CommandPingAdded;
[Commands.pingCancelled]: CommandPingCancelled;
}
export interface MapHandlers {
@@ -242,13 +252,15 @@ export enum OutCommand {
addSystemComment = 'addSystemComment',
deleteSystemComment = 'deleteSystemComment',
getSystemComments = 'getSystemComments',
// toggleTrack = 'toggle_track',
toggleFollow = 'toggle_follow',
getCharacterInfo = 'getCharacterInfo',
getCharactersTrackingInfo = 'getCharactersTrackingInfo',
updateCharacterTracking = 'updateCharacterTracking',
updateFollowingCharacter = 'updateFollowingCharacter',
updateMainCharacter = 'updateMainCharacter',
addPing = 'add_ping',
cancelPing = 'cancel_ping',
startTracking = 'startTracking',
// Only UI commands
openSettings = 'open_settings',
@@ -258,7 +270,7 @@ export enum OutCommand {
updateUserSettings = 'update_user_settings',
unlinkSignature = 'unlink_signature',
searchSystems = 'search_systems',
undoDeleteSignatures = 'undo_delete_signatures',
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type OutCommandHandler = <T = any>(event: { type: OutCommand; data: any }) => Promise<T>;
export type OutCommandHandler = <T = unknown>(event: { type: OutCommand; data: unknown }) => Promise<T>;

View File

@@ -4,7 +4,7 @@ import { CharacterTypeRaw } from '@/hooks/Mapper/types/character.ts';
import { SolarSystemRawType } from '@/hooks/Mapper/types/system.ts';
import { RoutesList } from '@/hooks/Mapper/types/routes.ts';
import { SolarSystemConnection } from '@/hooks/Mapper/types/connection.ts';
import { UserPermissions } from '@/hooks/Mapper/types';
import { PingData, UserPermissions } from '@/hooks/Mapper/types';
import { SystemSignature } from '@/hooks/Mapper/types/signatures';
export type MapUnionTypes = {
@@ -28,4 +28,5 @@ export type MapUnionTypes = {
mainCharacterEveId: string | null;
followingCharacterEveId: string | null;
pings: PingData[];
};

View File

@@ -0,0 +1,12 @@
export enum PingType {
Alert,
Rally,
}
export type PingData = {
inserted_at: number;
character_eve_id: string;
solar_system_id: string;
message: string;
type: PingType;
};

View File

@@ -30,6 +30,7 @@ export type GroupType = {
export type SignatureCustomInfo = {
k162Type?: string;
isEOL?: boolean;
isCrit?: boolean;
};
export type SystemSignature = {
@@ -46,6 +47,7 @@ export type SystemSignature = {
linked_system?: SolarSystemStaticInfoRaw;
inserted_at?: string;
updated_at?: string;
deleted?: boolean;
};
export interface ExtendedSystemSignature extends SystemSignature {
@@ -53,6 +55,7 @@ export interface ExtendedSystemSignature extends SystemSignature {
pendingAddition?: boolean;
pendingUntil?: number;
finalTimeoutId?: number;
deleted?: boolean;
}
export enum SignatureKindENG {
@@ -75,6 +78,26 @@ export enum SignatureKindRU {
Starbase = 'Starbase',
}
export enum SignatureKindFR {
CosmicSignature = 'Signature cosmique (type)',
CosmicAnomaly = 'Anomalie cosmique',
Structure = 'Structure',
Ship = 'Vaisseau',
Deployable = 'Déployable',
Drone = 'Drone',
Starbase = 'Base stellaire',
}
export enum SignatureKindDE {
CosmicSignature = 'Kosmische Signatur (typ)',
CosmicAnomaly = 'Kosmische Anomalie',
Structure = 'Struktur',
Ship = 'Schiff',
Deployable = 'Mobile Struktur',
Drone = 'Drohne',
Starbase = 'Sternenbasis',
}
export enum SignatureGroupENG {
CosmicSignature = 'Cosmic Signature',
Wormhole = 'Wormhole',
@@ -94,3 +117,23 @@ export enum SignatureGroupRU {
OreSite = 'Астероидный район',
CombatSite = 'Боевой район',
}
export enum SignatureGroupFR {
CosmicSignature = 'Signature cosmique (groupe)',
Wormhole = 'Trou de ver',
GasSite = 'Site de gaz',
RelicSite = 'Site de reliques',
DataSite = 'Site de données',
OreSite = 'Site de minerai',
CombatSite = 'Site de combat',
}
export enum SignatureGroupDE {
CosmicSignature = 'Kosmische Signatur (gruppe)',
Wormhole = 'Wurmloch',
GasSite = 'Gasgebiet',
RelicSite = 'Reliktgebiet',
DataSite = 'Datengebiet',
OreSite = 'Mineraliengebiet',
CombatSite = 'Kampfgebiet',
}

View File

@@ -1,9 +1,6 @@
import { MapHandlers } from '@/hooks/Mapper/types/mapHandlers.ts';
import { RefObject, useCallback } from 'react';
// Force reload the page after 5 minutes of inactivity
const FORCE_PAGE_RELOAD_TIMEOUT = 1000 * 60 * 5;
export const useMapperHandlers = (handlerRefs: RefObject<MapHandlers>[], hooksRef: RefObject<any>) => {
const handleCommand = useCallback(
async ({ type, data }) => {
@@ -16,13 +13,7 @@ export const useMapperHandlers = (handlerRefs: RefObject<MapHandlers>[], hooksRe
[hooksRef.current],
);
const handleMapEvent = useCallback(({ type, body, timestamp }) => {
const timeDiff = Date.now() - Date.parse(timestamp);
// If the event is older than the timeout, force reload the page
if (timeDiff > FORCE_PAGE_RELOAD_TIMEOUT) {
window.location.reload();
return;
}
const handleMapEvent = useCallback(({ type, body }) => {
handlerRefs.forEach(ref => {
if (!ref.current) {
return;

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@@ -53,16 +53,6 @@ public_api_disabled =
|> get_var_from_path_or_env("WANDERER_PUBLIC_API_DISABLED", "false")
|> String.to_existing_atom()
character_api_disabled =
config_dir
|> get_var_from_path_or_env("WANDERER_CHARACTER_API_DISABLED", "true")
|> String.to_existing_atom()
zkill_preload_disabled =
config_dir
|> get_var_from_path_or_env("WANDERER_ZKILL_PRELOAD_DISABLED", "false")
|> String.to_existing_atom()
map_subscriptions_enabled =
config_dir
|> get_var_from_path_or_env("WANDERER_MAP_SUBSCRIPTIONS_ENABLED", "false")
@@ -128,8 +118,13 @@ config :wanderer_app,
corp_id: System.get_env("WANDERER_CORP_ID", "-1") |> String.to_integer(),
corp_wallet: System.get_env("WANDERER_CORP_WALLET", ""),
public_api_disabled: public_api_disabled,
character_api_disabled: character_api_disabled,
zkill_preload_disabled: zkill_preload_disabled,
character_tracking_pause_disabled:
System.get_env("WANDERER_CHARACTER_TRACKING_PAUSE_DISABLED", "true")
|> String.to_existing_atom(),
character_api_disabled:
System.get_env("WANDERER_CHARACTER_API_DISABLED", "true") |> String.to_existing_atom(),
zkill_preload_disabled:
System.get_env("WANDERER_ZKILL_PRELOAD_DISABLED", "false") |> String.to_existing_atom(),
map_subscriptions_enabled: map_subscriptions_enabled,
map_connection_auto_expire_hours: map_connection_auto_expire_hours,
map_connection_auto_eol_hours: map_connection_auto_eol_hours,

View File

@@ -28,5 +28,6 @@ defmodule WandererApp.Api do
resource WandererApp.Api.UserTransaction
resource WandererApp.Api.CorpWalletTransaction
resource WandererApp.Api.License
resource WandererApp.Api.MapPing
end
end

Some files were not shown because too many files have changed in this diff Show More