Refactor user name display logic: integrate MiniMessageComponent in UserListComponent and transition to ProcessedMiniMessageNode. Add server state caching in ChatService with eager state dispatch on subscription.
This commit is contained in:
parent
8c02543bca
commit
1a0bc902ac
|
|
@ -37,6 +37,7 @@ public class ChatService {
|
|||
private final EventPublisher eventPublisher;
|
||||
private final NavigableMap<Instant, ChatMessage> chatMessages = new TreeMap<>();
|
||||
private final Map<String, EventUser> eventUserMap = new HashMap<>();
|
||||
private final Map<String, ServerDto> serverStateCache = new HashMap<>();
|
||||
|
||||
@Value("${chat.allowed-servers}")
|
||||
private String[] allowedServers;
|
||||
|
|
@ -73,7 +74,9 @@ public class ChatService {
|
|||
public SseEmitter subscribe(EventUser eventUser, String json) {
|
||||
String key = eventUser.uuid().toString();
|
||||
eventUserMap.put(key, eventUser);
|
||||
return eventPublisher.subscribe(key, json, this::handleSessionEnd);
|
||||
SseEmitter emitter = eventPublisher.subscribe(key, json, this::handleSessionEnd);
|
||||
sendServerStateToUser(key, eventUser);
|
||||
return emitter;
|
||||
}
|
||||
|
||||
private void handleSessionEnd(String key, Instant sessionStart, Instant sessionEnd) {
|
||||
|
|
@ -124,18 +127,26 @@ public class ChatService {
|
|||
sendMessagesToListeners(chatMessageList);
|
||||
}
|
||||
|
||||
public void updateServerState(ServerStateDto serverStateDto) {
|
||||
sendToUsers("server-state", (eventUser) -> {
|
||||
if (eventUser.hasPermission(PermissionClaimDto.HEAD_MOD)) {
|
||||
return ServerStateMapper.toJson(serverStateDto);
|
||||
public synchronized void updateServerState(ServerStateDto serverStateDto) {
|
||||
serverStateDto.getServers().forEach(serverDto -> serverStateCache.put(serverDto.getName(), serverDto));
|
||||
sendToUsers("server-state", this::getServerStateJson);
|
||||
}
|
||||
|
||||
List<ServerDto> filteredServers = serverStateDto.getServers().stream()
|
||||
private String getServerStateJson(EventUser eventUser) {
|
||||
if (eventUser.hasPermission(PermissionClaimDto.HEAD_MOD)) {
|
||||
return ServerStateMapper.toJson(new ServerStateDto().servers(serverStateCache.values().stream().toList()));
|
||||
}
|
||||
|
||||
List<ServerDto> filteredServers = serverStateCache.values().stream()
|
||||
.filter(serverDto -> Arrays.asList(allowedServers).contains(serverDto.getName()))
|
||||
.toList();
|
||||
|
||||
return ServerStateMapper.toJson(new ServerStateDto().servers(filteredServers));
|
||||
});
|
||||
}
|
||||
|
||||
private void sendServerStateToUser(String key, EventUser eventUser) {
|
||||
String json = getServerStateJson(eventUser);
|
||||
eventPublisher.sendToUser(key, "server-state", json);
|
||||
}
|
||||
|
||||
private void sendMessagesToListeners(List<ChatMessage> chatMessageList) {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@
|
|||
@for (player of server.players; track player.uuid) {
|
||||
<div class="user indented">
|
||||
<span class="user-name">
|
||||
@for (segment of getDisplayName(player); track $index) {
|
||||
<span [style.color]="segment.color">{{ segment.text }}</span>
|
||||
}
|
||||
<mini-message [node]="getDisplayName(player)"></mini-message>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import {Component, computed, inject} from '@angular/core';
|
||||
import {ChatService} from '@pages/altitude/chat/service/chat.service';
|
||||
import {NameFormatService} from '@pages/altitude/chat/service/name-format.service';
|
||||
import {ColoredNameSegment} from '@pages/altitude/chat/objects/colored-name-segment.object';
|
||||
import {User} from '@pages/altitude/chat/objects/server-state.object';
|
||||
import {ProcessedMiniMessageNode} from '@pages/altitude/chat/mini-message/mini-message.types';
|
||||
import {MiniMessageComponent} from '@pages/altitude/chat/components/mini-message/mini-message.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-list',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
imports: [MiniMessageComponent],
|
||||
templateUrl: './user-list.component.html',
|
||||
styleUrl: './user-list.component.scss'
|
||||
})
|
||||
|
|
@ -29,7 +30,7 @@ export class UserListComponent {
|
|||
};
|
||||
});
|
||||
|
||||
protected getDisplayName(user: User): ColoredNameSegment[] {
|
||||
return this.nameFormatService.parseColoredName(user.styledName || user.name);
|
||||
protected getDisplayName(user: User): ProcessedMiniMessageNode {
|
||||
return this.nameFormatService.getUserDisplayName(user);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@ import {inject, Injectable} from '@angular/core';
|
|||
import {ChatChannel} from '@pages/altitude/chat/objects/chat-channel.object';
|
||||
import {ColoredNameSegment} from '@pages/altitude/chat/objects/colored-name-segment.object';
|
||||
import {ChatService} from "./chat.service";
|
||||
import {User} from '@pages/altitude/chat/objects/server-state.object';
|
||||
import {normalizeComponent} from '@pages/altitude/chat/mini-message/normalize.util';
|
||||
import {precomputeNode} from '@pages/altitude/chat/mini-message/mini-message.util';
|
||||
import {ProcessedMiniMessageNode} from '@pages/altitude/chat/mini-message/mini-message.types';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class NameFormatService {
|
||||
|
|
@ -12,6 +16,18 @@ export class NameFormatService {
|
|||
return this.parseColoredName(this.getNameFromType(channel));
|
||||
}
|
||||
|
||||
public getUserDisplayName(user: User): ProcessedMiniMessageNode {
|
||||
if (user.styledName) {
|
||||
try {
|
||||
return precomputeNode(normalizeComponent(JSON.parse(user.styledName)));
|
||||
} catch {
|
||||
return precomputeNode(normalizeComponent({text: user.name}));
|
||||
}
|
||||
}
|
||||
|
||||
return precomputeNode(normalizeComponent({text: user.name}));
|
||||
}
|
||||
|
||||
private readonly LEGACY_COLOR_MAP: Record<string, string> = {
|
||||
'4': '#AA0000',
|
||||
'c': '#FF5555',
|
||||
|
|
@ -44,7 +60,7 @@ export class NameFormatService {
|
|||
return channel.name;
|
||||
}
|
||||
|
||||
public parseColoredName(name: string): ColoredNameSegment[] {
|
||||
private parseColoredName(name: string): ColoredNameSegment[] {
|
||||
const markerRegex = /\{#([0-9a-fA-F]{6})(<>|[<>]?)\}|&([0-9a-fA-F])/g;
|
||||
const segments: ColoredNameSegment[] = [];
|
||||
let currentColor: string | undefined;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user