mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 23:16:21 +00:00
Revert feature-folder migration; keep classic src/components + src/hooks layout
Decision: the src/features/<feature>/ layout introduced as proposal #3 (pilot on doorbell in 8ec9d27) is not the convention the team wants. The existing src/components/<area>/ + src/hooks/<area>/ split is the one that stays. What's reverted - src/features/doorbell/ is removed entirely. The doorbell view and the two hooks move back under the classic paths: src/features/doorbell/views/DoorbellWidgetView.tsx -> src/components/room/widgets/doorbell/DoorbellWidgetView.tsx src/features/doorbell/hooks/useDoorbellState.ts -> src/hooks/rooms/widgets/useDoorbellState.ts src/features/doorbell/hooks/useDoorbellActions.ts -> src/hooks/rooms/widgets/useDoorbellActions.ts - The compat shims that lived in those classic paths are dropped now that the real files are back. - src/hooks/rooms/widgets/index.ts adds the two new hooks alongside the existing useDoorbellWidget shim (kept as a deprecated wrapper so any external consumer importing the old shape via the barrel keeps working). What's preserved - The split between data and actions (proposal #4) — useDoorbellState and useDoorbellActions remain two separate hooks. This was the actual improvement, and it's independent of where the files sit. - The bug fixes from 8ec9d27 (close button race, optimistic-remove rollback) — both still present, just in the new path. - src/state/createNitroStore.ts and src/api/nitro-query/createNitroQuery.ts are left where they are. They aren't feature folders; they're cross-cutting framework code (Zustand skeleton, React Query adapter prototype) that any feature can consume. Doc - docs/ARCHITECTURE.md section #3 is rewritten to record the decision rather than recommend the layout. It now describes the convention to follow: * views under src/components/<area>/<feature>/ * hooks under src/hooks/<area>/<feature?>/ (siblings, not subfolders per widget) * sibling .types/.constants/.helpers files for view-specific code (e.g. WiredCreatorTools.*.ts) - "What's already in place" and "Recently fixed" sections updated to point at the new paths. - "How to pick the next refactor PR" no longer mentions feature-folder migration as an option. Note: the five extra feature folders started this session (reconnect, nitropedia, ads, hc-center, campaign) were never committed; they only existed in the working tree and have been restored from HEAD. Verification - find src/features -type f -> 0 (directory removed). - npx tsc --noEmit on all touched files: clean (only the project-wide pre-existing TS2307 about @nitrots/nitro-renderer not installed locally remains, same as before). - npx eslint on all touched files: 0 errors, 0 warnings. https://claude.ai/code/session_01GrR87LAqnAEyKG2ZbmQt5Q
This commit is contained in:
@@ -3,6 +3,8 @@ export * from './useAvatarInfoWidget';
|
||||
export * from './useChatCommandSelector';
|
||||
export * from './useChatInputWidget';
|
||||
export * from './useChatWidget';
|
||||
export * from './useDoorbellActions';
|
||||
export * from './useDoorbellState';
|
||||
export * from './useDoorbellWidget';
|
||||
export * from './useFilterWordsWidget';
|
||||
export * from './useFriendRequestWidget';
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { GetRoomSession } from '../../../api';
|
||||
|
||||
/**
|
||||
* Imperative actions for the doorbell. Stateless on purpose — split from
|
||||
* useDoorbellState so components that only need to dispatch an answer
|
||||
* don't subscribe to the events.
|
||||
*/
|
||||
export const useDoorbellActions = () => ({
|
||||
answer: (userName: string, flag: boolean): void =>
|
||||
{
|
||||
GetRoomSession()?.sendDoorbellApprovalMessage(userName, flag);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import { RoomSessionDoorbellEvent } from '@nitrots/nitro-renderer';
|
||||
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { useNitroEvent } from '../../events';
|
||||
|
||||
/**
|
||||
* Reduces the three doorbell events (DOORBELL, RSDE_ACCEPTED, RSDE_REJECTED)
|
||||
* into a single users array. Data-only hook split — actions live in
|
||||
* useDoorbellActions.
|
||||
*/
|
||||
export const useDoorbellState = (): readonly string[] =>
|
||||
{
|
||||
const [ users, setUsers ] = useState<string[]>([]);
|
||||
|
||||
const usersRef = useRef(users);
|
||||
|
||||
useLayoutEffect(() =>
|
||||
{
|
||||
usersRef.current = users;
|
||||
});
|
||||
|
||||
const handleAdd = useCallback((event: RoomSessionDoorbellEvent) =>
|
||||
{
|
||||
if(usersRef.current.indexOf(event.userName) >= 0) return;
|
||||
|
||||
setUsers([ ...usersRef.current, event.userName ]);
|
||||
}, []);
|
||||
|
||||
const handleRemove = useCallback((event: RoomSessionDoorbellEvent) =>
|
||||
{
|
||||
const index = usersRef.current.indexOf(event.userName);
|
||||
|
||||
if(index === -1) return;
|
||||
|
||||
const next = [ ...usersRef.current ];
|
||||
next.splice(index, 1);
|
||||
setUsers(next);
|
||||
}, []);
|
||||
|
||||
useNitroEvent<RoomSessionDoorbellEvent>(RoomSessionDoorbellEvent.DOORBELL, handleAdd);
|
||||
useNitroEvent<RoomSessionDoorbellEvent>(RoomSessionDoorbellEvent.RSDE_ACCEPTED, handleRemove);
|
||||
useNitroEvent<RoomSessionDoorbellEvent>(RoomSessionDoorbellEvent.RSDE_REJECTED, handleRemove);
|
||||
|
||||
return users;
|
||||
};
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useDoorbellActions, useDoorbellState } from '../../../features/doorbell';
|
||||
import { useDoorbellActions } from './useDoorbellActions';
|
||||
import { useDoorbellState } from './useDoorbellState';
|
||||
|
||||
/**
|
||||
* @deprecated Use `useDoorbellState` and `useDoorbellActions` from
|
||||
* `src/features/doorbell` directly. This shim is kept so existing
|
||||
* imports via the `hooks` barrel keep working.
|
||||
* @deprecated Use `useDoorbellState` and `useDoorbellActions` directly.
|
||||
* This shim preserves the old `{ users, answer }` shape so existing
|
||||
* imports keep working.
|
||||
*/
|
||||
export const useDoorbellWidget = () =>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user