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:
2026-08-09 02:04:11 +02:00
parent 8c02543bca
commit 1a0bc902ac
4 changed files with 45 additions and 19 deletions
@@ -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;