You've already forked Nitro_Render_V3
mirror of
https://github.com/duckietm/Nitro_Render_V3.git
synced 2026-06-20 15:36:18 +00:00
feat(session): snapshot getters for IgnoredUsersManager + GroupInformationManager
Extends the v2.1.0 React-friendly snapshot pattern (originally on SessionDataManager / RoomSessionManager) to two more session-state holders the React client reads frequently: - IgnoredUsersManager.getIgnoredUsersSnapshot(): ReadonlyArray<string> - GroupInformationManager.getGroupBadgesSnapshot(): ReadonlyMap<number, string> Both follow the same shape: lazy-frozen snapshot, cached until the underlying state mutates, then invalidated and a dispatched event lets the React client rebuild via useSyncExternalStore. Two new NitroEventType members carry the invalidation signal: - IGNORED_USERS_UPDATED — dispatched by IgnoredUsersManager whenever the list changes (initial load, add, remove, queue-truncate case 2). - GROUP_BADGES_UPDATED — dispatched by GroupInformationManager only when the incoming HabboGroupBadges payload contains at least one new or changed mapping (no-op refresh stays quiet). This lets the user-info popup, profile page, friend/guild filtering, and any other consumer share a single read through useSyncExternalStore instead of each subscribing to the underlying message events independently. API additions are interface-respecting and backwards-compatible — the existing `isIgnored(name)` / `getGroupBadge(groupId)` accessors stay untouched.
This commit is contained in:
@@ -2,4 +2,13 @@ export interface IGroupInformationManager
|
|||||||
{
|
{
|
||||||
init(): void;
|
init(): void;
|
||||||
getGroupBadge(groupId: number): string;
|
getGroupBadge(groupId: number): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current `groupId -> badgeId` map as a frozen,
|
||||||
|
* referentially stable ReadonlyMap. The same reference is returned
|
||||||
|
* across reads until the underlying badges change; mutations
|
||||||
|
* dispatch `NitroEventType.GROUP_BADGES_UPDATED` to signal
|
||||||
|
* invalidation.
|
||||||
|
*/
|
||||||
|
getGroupBadgesSnapshot(): ReadonlyMap<number, string>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,14 @@ export interface IIgnoredUsersManager
|
|||||||
ignoreUser(name: string): void;
|
ignoreUser(name: string): void;
|
||||||
unignoreUser(name: string): void;
|
unignoreUser(name: string): void;
|
||||||
isIgnored(name: string): boolean;
|
isIgnored(name: string): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current ignored-users list as a frozen, referentially
|
||||||
|
* stable array. The same reference is returned across reads until
|
||||||
|
* the list is mutated; mutations dispatch
|
||||||
|
* `NitroEventType.IGNORED_USERS_UPDATED` to signal invalidation.
|
||||||
|
*
|
||||||
|
* Pairs with `useSyncExternalStore` on the React client.
|
||||||
|
*/
|
||||||
|
getIgnoredUsersSnapshot(): ReadonlyArray<string>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,6 @@ export class NitroEventType
|
|||||||
public static readonly FURNITURE_DATA_LOADED = 'FURNITURE_DATA_LOADED';
|
public static readonly FURNITURE_DATA_LOADED = 'FURNITURE_DATA_LOADED';
|
||||||
public static readonly SESSION_DATA_UPDATED = 'SESSION_DATA_UPDATED';
|
public static readonly SESSION_DATA_UPDATED = 'SESSION_DATA_UPDATED';
|
||||||
public static readonly ROOM_SESSION_UPDATED = 'ROOM_SESSION_UPDATED';
|
public static readonly ROOM_SESSION_UPDATED = 'ROOM_SESSION_UPDATED';
|
||||||
|
public static readonly IGNORED_USERS_UPDATED = 'IGNORED_USERS_UPDATED';
|
||||||
|
public static readonly GROUP_BADGES_UPDATED = 'GROUP_BADGES_UPDATED';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { IGroupInformationManager } from '@nitrots/api';
|
import { IGroupInformationManager } from '@nitrots/api';
|
||||||
import { GetCommunication, GetHabboGroupBadgesMessageComposer, HabboGroupBadgesMessageEvent, RoomReadyMessageEvent } from '@nitrots/communication';
|
import { GetCommunication, GetHabboGroupBadgesMessageComposer, HabboGroupBadgesMessageEvent, RoomReadyMessageEvent } from '@nitrots/communication';
|
||||||
|
import { GetEventDispatcher, NitroEvent, NitroEventType } from '@nitrots/events';
|
||||||
|
|
||||||
export class GroupInformationManager implements IGroupInformationManager
|
export class GroupInformationManager implements IGroupInformationManager
|
||||||
{
|
{
|
||||||
private _groupBadges: Map<number, string> = new Map();
|
private _groupBadges: Map<number, string> = new Map();
|
||||||
|
private _groupBadgesSnapshot: ReadonlyMap<number, string> | null = null;
|
||||||
|
|
||||||
public init(): void
|
public init(): void
|
||||||
{
|
{
|
||||||
@@ -20,11 +22,37 @@ export class GroupInformationManager implements IGroupInformationManager
|
|||||||
{
|
{
|
||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
|
|
||||||
for(const [groupId, badgeId] of parser.badges.entries()) this._groupBadges.set(groupId, badgeId);
|
let didChange = false;
|
||||||
|
|
||||||
|
for(const [ groupId, badgeId ] of parser.badges.entries())
|
||||||
|
{
|
||||||
|
if(this._groupBadges.get(groupId) === badgeId) continue;
|
||||||
|
|
||||||
|
this._groupBadges.set(groupId, badgeId);
|
||||||
|
didChange = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(didChange) this.invalidateGroupBadgesSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
private invalidateGroupBadgesSnapshot(): void
|
||||||
|
{
|
||||||
|
this._groupBadgesSnapshot = null;
|
||||||
|
|
||||||
|
GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.GROUP_BADGES_UPDATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
public getGroupBadge(groupId: number): string
|
public getGroupBadge(groupId: number): string
|
||||||
{
|
{
|
||||||
return this._groupBadges.get(groupId) ?? '';
|
return this._groupBadges.get(groupId) ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getGroupBadgesSnapshot(): ReadonlyMap<number, string>
|
||||||
|
{
|
||||||
|
if(this._groupBadgesSnapshot) return this._groupBadgesSnapshot;
|
||||||
|
|
||||||
|
this._groupBadgesSnapshot = new Map(this._groupBadges) as ReadonlyMap<number, string>;
|
||||||
|
|
||||||
|
return this._groupBadgesSnapshot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,27 @@
|
|||||||
import { IIgnoredUsersManager } from '@nitrots/api';
|
import { IIgnoredUsersManager } from '@nitrots/api';
|
||||||
import { GetCommunication, GetIgnoredUsersComposer, IgnoreResultEvent, IgnoreUserComposer, IgnoreUserIdComposer, IgnoredUsersEvent, UnignoreUserComposer } from '@nitrots/communication';
|
import { GetCommunication, GetIgnoredUsersComposer, IgnoreResultEvent, IgnoreUserComposer, IgnoreUserIdComposer, IgnoredUsersEvent, UnignoreUserComposer } from '@nitrots/communication';
|
||||||
|
import { GetEventDispatcher, NitroEvent, NitroEventType } from '@nitrots/events';
|
||||||
|
|
||||||
export class IgnoredUsersManager implements IIgnoredUsersManager
|
export class IgnoredUsersManager implements IIgnoredUsersManager
|
||||||
{
|
{
|
||||||
private _ignoredUsers: string[] = [];
|
private _ignoredUsers: string[] = [];
|
||||||
|
private _ignoredUsersSnapshot: ReadonlyArray<string> | null = null;
|
||||||
|
|
||||||
|
private invalidateIgnoredUsersSnapshot(): void
|
||||||
|
{
|
||||||
|
this._ignoredUsersSnapshot = null;
|
||||||
|
|
||||||
|
GetEventDispatcher().dispatchEvent(new NitroEvent(NitroEventType.IGNORED_USERS_UPDATED));
|
||||||
|
}
|
||||||
|
|
||||||
|
public getIgnoredUsersSnapshot(): ReadonlyArray<string>
|
||||||
|
{
|
||||||
|
if(this._ignoredUsersSnapshot) return this._ignoredUsersSnapshot;
|
||||||
|
|
||||||
|
this._ignoredUsersSnapshot = Object.freeze<string[]>([ ...this._ignoredUsers ]) as ReadonlyArray<string>;
|
||||||
|
|
||||||
|
return this._ignoredUsersSnapshot;
|
||||||
|
}
|
||||||
|
|
||||||
public init(): void
|
public init(): void
|
||||||
{
|
{
|
||||||
@@ -25,6 +43,7 @@ export class IgnoredUsersManager implements IIgnoredUsersManager
|
|||||||
if(!parser) return;
|
if(!parser) return;
|
||||||
|
|
||||||
this._ignoredUsers = parser.ignoredUsers;
|
this._ignoredUsers = parser.ignoredUsers;
|
||||||
|
this.invalidateIgnoredUsersSnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onIgnoreResultEvent(event: IgnoreResultEvent): void
|
private onIgnoreResultEvent(event: IgnoreResultEvent): void
|
||||||
@@ -47,6 +66,7 @@ export class IgnoredUsersManager implements IIgnoredUsersManager
|
|||||||
case 2:
|
case 2:
|
||||||
this.addUserToIgnoreList(name);
|
this.addUserToIgnoreList(name);
|
||||||
this._ignoredUsers.shift();
|
this._ignoredUsers.shift();
|
||||||
|
this.invalidateIgnoredUsersSnapshot();
|
||||||
return;
|
return;
|
||||||
case 3:
|
case 3:
|
||||||
this.removeUserFromIgnoreList(name);
|
this.removeUserFromIgnoreList(name);
|
||||||
@@ -56,14 +76,20 @@ export class IgnoredUsersManager implements IIgnoredUsersManager
|
|||||||
|
|
||||||
private addUserToIgnoreList(name: string): void
|
private addUserToIgnoreList(name: string): void
|
||||||
{
|
{
|
||||||
if(this._ignoredUsers.indexOf(name) < 0) this._ignoredUsers.push(name);
|
if(this._ignoredUsers.indexOf(name) >= 0) return;
|
||||||
|
|
||||||
|
this._ignoredUsers.push(name);
|
||||||
|
this.invalidateIgnoredUsersSnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeUserFromIgnoreList(name: string): void
|
private removeUserFromIgnoreList(name: string): void
|
||||||
{
|
{
|
||||||
const index = this._ignoredUsers.indexOf(name);
|
const index = this._ignoredUsers.indexOf(name);
|
||||||
|
|
||||||
if(index >= 0) this._ignoredUsers.splice(index, 1);
|
if(index < 0) return;
|
||||||
|
|
||||||
|
this._ignoredUsers.splice(index, 1);
|
||||||
|
this.invalidateIgnoredUsersSnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ignoreUserId(id: number): void
|
public ignoreUserId(id: number): void
|
||||||
|
|||||||
Reference in New Issue
Block a user