mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
Split useUserChooserWidget into state + actions (flat hooks layout)
Speculare di useFurniChooserWidget — stesso split + stesso layout (flat
in src/hooks/rooms/widgets/). User chooser è il gemello del furni
chooser nella shape: items list popolata da room scan + due bridge
events (added/removed) + selectItem imperativo.
Split
- src/hooks/rooms/widgets/useUserChooserState.ts (new):
items + onClose + populateChooser + useUserAddedEvent +
useUserRemovedEvent. Helper buildUserItem dedupa la costruzione
di RoomObjectItem fra populateChooser e l'add handler (~20
righe di duplicazione in meno).
Plus: aggiunto ?. su roomSession e userDataManager (lo stesso
bug pattern del PetTrainingPanel fixato altrove).
- src/hooks/rooms/widgets/useUserChooserActions.ts (new):
selectItem puro.
- src/hooks/rooms/widgets/useUserChooserWidget.ts: kept as a
deprecated shim that composes both and preserves
{ items, onClose, selectItem, populateChooser } per il consumer
UserChooserWidgetView.
Verifica
- yarn eslint sui 4 file toccati: 0 errors / 0 warnings.
- yarn test: 49/49 passing.
- yarn tsc: clean.
Sequenza god-hook split adesso a 4 (doorbell, poll, furni-chooser,
user-chooser). Rimangono: useFriendRequestWidget, usePetPackageWidget,
useWordQuizWidget, useChatInputWidget, useChatWidget,
useAvatarInfoWidget, useFilterWordsWidget.
This commit is contained in:
@@ -15,5 +15,7 @@ export * from './usePetPackageWidget';
|
||||
export * from './usePollActions';
|
||||
export * from './usePollSubscriptions';
|
||||
export * from './usePollWidget';
|
||||
export * from './useUserChooserActions';
|
||||
export * from './useUserChooserState';
|
||||
export * from './useUserChooserWidget';
|
||||
export * from './useWordQuizWidget';
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { GetRoomEngine } from '@nitrots/nitro-renderer';
|
||||
import { GetRoomSession, RoomObjectItem } from '../../../api';
|
||||
|
||||
/**
|
||||
* Imperative actions for the User chooser. Stateless — split from
|
||||
* useUserChooserState so components that only need to dispatch a
|
||||
* selection don't subscribe to the user-add/remove lifecycle events.
|
||||
*/
|
||||
export const useUserChooserActions = () => ({
|
||||
selectItem: (item: RoomObjectItem): void =>
|
||||
{
|
||||
if(!item) return;
|
||||
|
||||
GetRoomEngine().selectRoomObject(GetRoomSession().roomId, item.id, item.category);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
import { GetRoomEngine, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||
import { useState } from 'react';
|
||||
import { GetRoomSession, RoomObjectItem } from '../../../api';
|
||||
import { useUserAddedEvent, useUserRemovedEvent } from '../engine';
|
||||
|
||||
const resolveUserType = (userType: number): string =>
|
||||
{
|
||||
switch(userType)
|
||||
{
|
||||
case 1: return 'Habbo';
|
||||
case 2: return 'Pet';
|
||||
case 3: return 'Bot';
|
||||
default: return '-';
|
||||
}
|
||||
};
|
||||
|
||||
const buildUserItem = (roomIndex: number): RoomObjectItem | null =>
|
||||
{
|
||||
if(roomIndex < 0) return null;
|
||||
|
||||
const userData = GetRoomSession()?.userDataManager?.getUserDataByIndex(roomIndex);
|
||||
|
||||
if(!userData) return null;
|
||||
if(userData.type !== 1) return null;
|
||||
|
||||
return new RoomObjectItem(userData.roomIndex, RoomObjectCategory.UNIT, userData.name, 0, '-', resolveUserType(userData.type));
|
||||
};
|
||||
|
||||
/**
|
||||
* State + event subscriptions for the User chooser widget. Pure
|
||||
* imperative actions (selectItem) live in useUserChooserActions.
|
||||
*/
|
||||
export const useUserChooserState = () =>
|
||||
{
|
||||
const [ items, setItems ] = useState<RoomObjectItem[]>(null);
|
||||
|
||||
const onClose = () => setItems(null);
|
||||
|
||||
const populateChooser = () =>
|
||||
{
|
||||
const session = GetRoomSession();
|
||||
|
||||
if(!session) return;
|
||||
|
||||
const roomObjects = GetRoomEngine().getRoomObjects(session.roomId, RoomObjectCategory.UNIT);
|
||||
|
||||
setItems(roomObjects
|
||||
.map(roomObject => buildUserItem(roomObject.id))
|
||||
.filter((item): item is RoomObjectItem => item !== null)
|
||||
.sort((a, b) => ((a.name < b.name) ? -1 : 1)));
|
||||
};
|
||||
|
||||
useUserAddedEvent(!!items, event =>
|
||||
{
|
||||
const item = buildUserItem(event.id);
|
||||
|
||||
if(!item) return;
|
||||
|
||||
setItems(prevValue =>
|
||||
{
|
||||
const newValue = [ ...(prevValue ?? []), item ];
|
||||
newValue.sort((a, b) => ((a.name < b.name) ? -1 : 1));
|
||||
return newValue;
|
||||
});
|
||||
});
|
||||
|
||||
useUserRemovedEvent(!!items, event =>
|
||||
{
|
||||
if(event.id < 0) return;
|
||||
|
||||
setItems(prevValue =>
|
||||
{
|
||||
if(!prevValue) return prevValue;
|
||||
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
for(let i = 0; i < newValue.length; i++)
|
||||
{
|
||||
const existingValue = newValue[i];
|
||||
|
||||
if((existingValue.id !== event.id) || (existingValue.category !== event.category)) continue;
|
||||
|
||||
newValue.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
});
|
||||
|
||||
return { items, onClose, populateChooser };
|
||||
};
|
||||
@@ -1,97 +1,16 @@
|
||||
import { GetRoomEngine, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||
import { useState } from 'react';
|
||||
import { GetRoomSession, RoomObjectItem } from '../../../api';
|
||||
import { useUserAddedEvent, useUserRemovedEvent } from '../engine';
|
||||
import { useRoom } from '../useRoom';
|
||||
import { useUserChooserActions } from './useUserChooserActions';
|
||||
import { useUserChooserState } from './useUserChooserState';
|
||||
|
||||
const resolveUserType = (userType: number): string =>
|
||||
/**
|
||||
* @deprecated Use `useUserChooserState` (data + close + populate) and
|
||||
* `useUserChooserActions` (imperative selectItem) directly. This shim
|
||||
* preserves the `{ items, onClose, selectItem, populateChooser }` shape
|
||||
* for existing consumers.
|
||||
*/
|
||||
export const useUserChooserWidget = () =>
|
||||
{
|
||||
switch(userType)
|
||||
{
|
||||
case 1: return 'Habbo';
|
||||
case 2: return 'Pet';
|
||||
case 3: return 'Bot';
|
||||
default: return '-';
|
||||
}
|
||||
};
|
||||
|
||||
const useUserChooserWidgetState = () =>
|
||||
{
|
||||
const [ items, setItems ] = useState<RoomObjectItem[]>(null);
|
||||
const { roomSession = null } = useRoom();
|
||||
|
||||
const onClose = () => setItems(null);
|
||||
|
||||
const selectItem = (item: RoomObjectItem) => item && GetRoomEngine().selectRoomObject(GetRoomSession().roomId, item.id, item.category);
|
||||
|
||||
const populateChooser = () =>
|
||||
{
|
||||
const roomSession = GetRoomSession();
|
||||
const roomObjects = GetRoomEngine().getRoomObjects(roomSession.roomId, RoomObjectCategory.UNIT);
|
||||
|
||||
setItems(roomObjects
|
||||
.map(roomObject =>
|
||||
{
|
||||
if(roomObject.id < 0) return null;
|
||||
|
||||
const userData = roomSession.userDataManager.getUserDataByIndex(roomObject.id);
|
||||
|
||||
if(!userData) return null;
|
||||
if(userData.type !== 1) return null;
|
||||
|
||||
const type = resolveUserType(userData.type);
|
||||
return new RoomObjectItem(userData.roomIndex, RoomObjectCategory.UNIT, userData.name, 0, '-', type);
|
||||
})
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => ((a.name < b.name) ? -1 : 1)));
|
||||
};
|
||||
|
||||
useUserAddedEvent(!!items, event =>
|
||||
{
|
||||
if(event.id < 0) return;
|
||||
|
||||
const userData = GetRoomSession().userDataManager.getUserDataByIndex(event.id);
|
||||
|
||||
if(!userData) return;
|
||||
if(userData.type !== 1) return;
|
||||
|
||||
const type = resolveUserType(userData.type);
|
||||
|
||||
setItems(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
newValue.push(new RoomObjectItem(userData.roomIndex, RoomObjectCategory.UNIT, userData.name, 0, '-', type));
|
||||
newValue.sort((a, b) => ((a.name < b.name) ? -1 : 1));
|
||||
|
||||
return newValue;
|
||||
});
|
||||
});
|
||||
|
||||
useUserRemovedEvent(!!items, event =>
|
||||
{
|
||||
if(event.id < 0) return;
|
||||
|
||||
setItems(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
for(let i = 0; i < newValue.length; i++)
|
||||
{
|
||||
const existingValue = newValue[i];
|
||||
|
||||
if((existingValue.id !== event.id) || (existingValue.category !== event.category)) continue;
|
||||
|
||||
newValue.splice(i, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
});
|
||||
const { items, onClose, populateChooser } = useUserChooserState();
|
||||
const { selectItem } = useUserChooserActions();
|
||||
|
||||
return { items, onClose, selectItem, populateChooser };
|
||||
};
|
||||
|
||||
export const useUserChooserWidget = useUserChooserWidgetState;
|
||||
|
||||
Reference in New Issue
Block a user