mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
Split useFriendRequestWidget into state + actions (flat hooks layout)
Stesso pattern di doorbell / poll / furni-chooser / user-chooser:
flat split sotto src/hooks/rooms/widgets/, no co-location dentro
src/components/.
Split
- src/hooks/rooms/widgets/useFriendRequestState.ts (new):
activeRequests state + displayedRequests derived (filter su
dismissedRequestIds) + due bridge events (user added/removed) +
un useEffect che riallinea activeRequests quando cambia il set
di requests dal friends-store. Esporta anche il tipo
ActiveFriendRequest per consumi futuri.
Plus: ?. su roomSession e userDataManager per evitare il bug
pattern "session è null in transition" (vedi PetTrainingPanel,
precedentemente fixato).
- src/hooks/rooms/widgets/useFriendRequestActions.ts (new):
hideFriendRequest. Thin adapter sul friends-store
(setDismissedRequestIds), nessuna subscription.
- src/hooks/rooms/widgets/useFriendRequestWidget.ts: deprecated
shim che compone i due e preserva
{ displayedRequests, hideFriendRequest } per il consumer
FriendRequestWidgetView.
Verifica
- yarn eslint sui 4 file toccati: 1 errore pre-esistente
(set-state-in-effect sul useEffect che ri-derive activeRequests
da requests — già nel file originale, baseline invariata).
- yarn test: 49/49 passing.
- yarn tsc: clean.
Sequence widget split adesso a 5 (doorbell, poll, furni-chooser,
user-chooser, friend-request). Rimangono: usePetPackageWidget,
useWordQuizWidget, useChatInputWidget, useChatWidget,
useAvatarInfoWidget, useFilterWordsWidget.
This commit is contained in:
@@ -7,6 +7,8 @@ export * from './useDoorbellActions';
|
||||
export * from './useDoorbellState';
|
||||
export * from './useDoorbellWidget';
|
||||
export * from './useFilterWordsWidget';
|
||||
export * from './useFriendRequestActions';
|
||||
export * from './useFriendRequestState';
|
||||
export * from './useFriendRequestWidget';
|
||||
export * from './useFurniChooserActions';
|
||||
export * from './useFurniChooserState';
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { useFriends } from '../../friends';
|
||||
|
||||
/**
|
||||
* Imperative actions for the friend-request widget. Stateless — split
|
||||
* from useFriendRequestState so a component that only needs to dismiss
|
||||
* a request doesn't subscribe to the user-added/removed lifecycle.
|
||||
*
|
||||
* The actual dismissal flag lives in the shared friends store
|
||||
* (via `setDismissedRequestIds`), so this hook is a thin adapter.
|
||||
*/
|
||||
export const useFriendRequestActions = () =>
|
||||
{
|
||||
const { setDismissedRequestIds = null } = useFriends();
|
||||
|
||||
return {
|
||||
hideFriendRequest: (userId: number): void =>
|
||||
{
|
||||
if(!setDismissedRequestIds) return;
|
||||
|
||||
setDismissedRequestIds(prevValue =>
|
||||
{
|
||||
if(prevValue.indexOf(userId) >= 0) return prevValue;
|
||||
|
||||
return [ ...prevValue, userId ];
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
import { RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { GetRoomSession, MessengerRequest } from '../../../api';
|
||||
import { useFriends } from '../../friends';
|
||||
import { useUserAddedEvent, useUserRemovedEvent } from '../engine';
|
||||
|
||||
export interface ActiveFriendRequest
|
||||
{
|
||||
roomIndex: number;
|
||||
request: MessengerRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* State + event subscriptions for the friend-request room widget.
|
||||
* Pure imperative action (hideFriendRequest) lives in
|
||||
* useFriendRequestActions.
|
||||
*/
|
||||
export const useFriendRequestState = () =>
|
||||
{
|
||||
const [ activeRequests, setActiveRequests ] = useState<ActiveFriendRequest[]>([]);
|
||||
const { requests = [], dismissedRequestIds = [] } = useFriends();
|
||||
|
||||
const displayedRequests = useMemo(
|
||||
() => activeRequests.filter(entry => (dismissedRequestIds.indexOf(entry.request.requesterUserId) === -1)),
|
||||
[ activeRequests, dismissedRequestIds ]
|
||||
);
|
||||
|
||||
useUserAddedEvent(true, event =>
|
||||
{
|
||||
if(event.category !== RoomObjectCategory.UNIT) return;
|
||||
|
||||
const userData = GetRoomSession()?.userDataManager?.getUserDataByIndex(event.id);
|
||||
|
||||
if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return;
|
||||
|
||||
const request = requests.find(r => (r.requesterUserId === userData.webID));
|
||||
|
||||
if(!request) return;
|
||||
|
||||
setActiveRequests(prev =>
|
||||
{
|
||||
if(prev.find(entry => (entry.request.requesterUserId === userData.webID))) return prev;
|
||||
|
||||
return [ ...prev, { roomIndex: userData.roomIndex, request } ];
|
||||
});
|
||||
});
|
||||
|
||||
useUserRemovedEvent(true, event =>
|
||||
{
|
||||
if(event.category !== RoomObjectCategory.UNIT) return;
|
||||
|
||||
setActiveRequests(prev =>
|
||||
{
|
||||
const index = prev.findIndex(entry => (entry.roomIndex === event.id));
|
||||
|
||||
if(index === -1) return prev;
|
||||
|
||||
const next = [ ...prev ];
|
||||
next.splice(index, 1);
|
||||
return next;
|
||||
});
|
||||
});
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const session = GetRoomSession();
|
||||
|
||||
if(!session) return;
|
||||
|
||||
const next: ActiveFriendRequest[] = [];
|
||||
|
||||
for(const request of requests)
|
||||
{
|
||||
const userData = session.userDataManager?.getUserData(request.requesterUserId);
|
||||
|
||||
if(!userData) continue;
|
||||
|
||||
next.push({ roomIndex: userData.roomIndex, request });
|
||||
}
|
||||
|
||||
setActiveRequests(next);
|
||||
}, [ requests ]);
|
||||
|
||||
return { displayedRequests };
|
||||
};
|
||||
@@ -1,81 +1,15 @@
|
||||
import { RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { GetRoomSession, MessengerRequest } from '../../../api';
|
||||
import { useFriends } from '../../friends';
|
||||
import { useUserAddedEvent, useUserRemovedEvent } from '../engine';
|
||||
import { useFriendRequestActions } from './useFriendRequestActions';
|
||||
import { useFriendRequestState } from './useFriendRequestState';
|
||||
|
||||
const useFriendRequestWidgetState = () =>
|
||||
/**
|
||||
* @deprecated Use `useFriendRequestState` and `useFriendRequestActions`
|
||||
* directly. This shim preserves the
|
||||
* `{ displayedRequests, hideFriendRequest }` shape for existing consumers.
|
||||
*/
|
||||
export const useFriendRequestWidget = () =>
|
||||
{
|
||||
const [ activeRequests, setActiveRequests ] = useState<{ roomIndex: number, request: MessengerRequest }[]>([]);
|
||||
const { requests = [], dismissedRequestIds = [], setDismissedRequestIds = null } = useFriends();
|
||||
|
||||
const displayedRequests = useMemo(() => activeRequests.filter(request => (dismissedRequestIds.indexOf(request.request.requesterUserId) === -1)), [ activeRequests, dismissedRequestIds ]);
|
||||
|
||||
const hideFriendRequest = (userId: number) =>
|
||||
{
|
||||
setDismissedRequestIds(prevValue =>
|
||||
{
|
||||
if(prevValue.indexOf(userId) >= 0) return prevValue;
|
||||
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
newValue.push(userId);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
};
|
||||
|
||||
useUserAddedEvent(true, event =>
|
||||
{
|
||||
if(event.category !== RoomObjectCategory.UNIT) return;
|
||||
|
||||
const userData = GetRoomSession().userDataManager.getUserDataByIndex(event.id);
|
||||
|
||||
if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return;
|
||||
|
||||
const request = requests.find(request => (request.requesterUserId === userData.webID));
|
||||
|
||||
if(!request || activeRequests.find(request => (request.request.requesterUserId === userData.webID))) return;
|
||||
|
||||
const newValue = [ ...activeRequests ];
|
||||
|
||||
newValue.push({ roomIndex: userData.roomIndex, request });
|
||||
|
||||
setActiveRequests(newValue);
|
||||
});
|
||||
|
||||
useUserRemovedEvent(true, event =>
|
||||
{
|
||||
if(event.category !== RoomObjectCategory.UNIT) return;
|
||||
|
||||
const index = activeRequests.findIndex(request => (request.roomIndex === event.id));
|
||||
|
||||
if(index === -1) return;
|
||||
|
||||
const newValue = [ ...activeRequests ];
|
||||
|
||||
newValue.splice(index, 1);
|
||||
|
||||
setActiveRequests(newValue);
|
||||
});
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const newDisplayedRequests: { roomIndex: number, request: MessengerRequest }[] = [];
|
||||
|
||||
for(const request of requests)
|
||||
{
|
||||
const userData = GetRoomSession().userDataManager.getUserData(request.requesterUserId);
|
||||
|
||||
if(!userData) continue;
|
||||
|
||||
newDisplayedRequests.push({ roomIndex: userData.roomIndex, request });
|
||||
}
|
||||
|
||||
setActiveRequests(newDisplayedRequests);
|
||||
}, [ requests ]);
|
||||
const { displayedRequests } = useFriendRequestState();
|
||||
const { hideFriendRequest } = useFriendRequestActions();
|
||||
|
||||
return { displayedRequests, hideFriendRequest };
|
||||
};
|
||||
|
||||
export const useFriendRequestWidget = useFriendRequestWidgetState;
|
||||
|
||||
Reference in New Issue
Block a user