Commit Graph

135 Commits

Author SHA1 Message Date
simoleo89 0755285708 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
2026-05-11 16:31:53 +00:00
simoleo89 48d62c5c6b Architecture refactor: docs + 5 pilot implementations + error boundary
This is the structural plan promised in the previous session, with concrete
pilots for all five proposals + the bonus error-boundary work.

== docs/ARCHITECTURE.md (new, ~370 lines)

Living document describing:
- where the project stands today (event-bus pattern friction with React 19,
  god-hooks, oversized files);
- the five proposed structural improvements with the why/how/status of each;
- what's already in place across this branch;
- recommended order for the next refactor PRs.

This is the deliverable the rest of this commit references.

== Proposal #3 + #4 pilots: src/features/doorbell/ (new)

Concrete feature-folder migration on the doorbell widget (chosen because
it's small enough to migrate end-to-end in one commit).

  src/features/doorbell/
    index.ts                    public API
    views/DoorbellWidgetView.tsx
    hooks/useDoorbellState.ts   reduces 3 events into a users array (data only)
    hooks/useDoorbellActions.ts answer(name, flag) (imperative actions only)

The split (data vs actions) is the pattern proposal #4 wants applied to
useCatalog/useChat/useWiredTools later. The original useDoorbellWidget had
both concerns + a buggy `useEffect(() => setIsVisible(!!users.length), [users])`
derive-state-in-effect. The new view computes visibility in render.

Compat shims kept so existing imports keep working:
- src/components/room/widgets/doorbell/DoorbellWidgetView.tsx -> 1-line re-export
- src/hooks/rooms/widgets/useDoorbellWidget.ts -> deprecated wrapper around
  the two new hooks, returning the same { users, answer } shape.

== Proposal #2 prototype: src/api/nitro-query/ (new)

Adapter outline for wrapping composer/parser request-response pairs in
TanStack Query. Not yet enabled because @tanstack/react-query is not in
package.json. The file documents the activation steps:

  yarn add @tanstack/react-query @tanstack/react-query-devtools
  + mount QueryClientProvider in src/index.tsx

awaitNitroResponse() throws with a helpful pointer to the doc section if
called before activation, so accidental adoption fails loudly.

== Proposal #5 skeleton: src/state/createNitroStore.ts (new)

Same pattern: skeleton + activation instructions. Not yet enabled because
zustand is not in package.json.

  yarn add zustand
  + replace the throw with `import { create } from 'zustand'; export const createNitroStore = create;`

The doc inside the file shows the recommended slice shape and points to
the suggested first migration target (the let isCreatingRoom singleton in
NavigatorRoomCreatorView).

== Bonus: WidgetErrorBoundary

src/common/error-boundary/WidgetErrorBoundary.tsx wraps react-error-boundary
with a sensible default (silent fallback, NitroLogger.error). Re-exported
from src/common/index.ts.

Applied as the umbrella around RoomWidgetsView's children — a widget
crash in a room (e.g. malformed pet data) now degrades gracefully
instead of unmounting the whole UI.

== Verification

- yarn eslint on all new + modified files: 0 errors / 0 warnings introduced.
  RoomWidgetsView still has its 1 pre-existing FC<{}> error (1 before, 1 after).
- yarn tsc on all new files: clean (only project-wide pre-existing
  TS2307 about @nitrots/nitro-renderer not installed locally remains).
- No regressions: existing imports of DoorbellWidgetView and
  useDoorbellWidget keep resolving via the compat shims.

== What's NOT in this commit (intentionally)

- Mass adoption of the new patterns elsewhere — left as follow-up PRs in
  the order documented in ARCHITECTURE.md "How to pick the next refactor PR".
- Installation of @tanstack/react-query / zustand — explicit team decision,
  not the LLM's to make.
- Test infrastructure (Vitest setup) — listed as the #1 missing piece in
  the doc, but a separate PR.

https://claude.ai/code/session_01GrR87LAqnAEyKG2ZbmQt5Q
2026-05-11 16:31:52 +00:00
simoleo89 22a44d18b0 Add useNitroEventState / useMessageEventState hooks (proposal #1)
Introduce the building block for reducing the state-from-event
boilerplate that pervades the codebase:

  // Before
  const [foo, setFoo] = useState(initial);
  useNitroEvent(SOME_EVENT, e => setFoo(e.payload));

  // After
  const foo = useNitroEventState(SOME_EVENT, e => e.payload, initial);

Implementation notes:
- src/hooks/events/useNitroEventState.ts wraps useNitroEvent so the
  selector closure can use up-to-date surrounding values (captured in
  a ref refreshed in commit via useLayoutEffect) without forcing a
  re-subscription on every render. Listener is registered once and
  always reads the latest selector.
- src/hooks/events/useMessageEventState.ts is the mirror for
  useMessageEvent (server message channel — request/response composers
  and push parsers).
- Both pass the new react-hooks v7 rules cleanly (in particular the
  strict react-hooks/refs that forbids ref mutation during render).
- Re-exported from src/hooks/events/index.ts so callers reach them
  via the existing `from '../../hooks'` import path.

Pilot adoption (1 site) to demonstrate the pattern:
- src/components/catalog/views/targeted-offer/OfferView.tsx:
  the offer state was a clean derive-from-event case
  (setOffer(parser.data) on TargetedOfferEvent, no other writes).
  Replaced with a single useMessageEventState call using the optional
  chain `evt.getParser()?.data ?? null` as selector. Removes the
  useState pair and the explicit subscription block.

Honest scope note:
A broader sweep is intentionally NOT done. Most existing event
subscriptions in this codebase are multi-state updates, state
machines, conditional filters ("skip if not my id"), or have side
effects mixed in (notifications, redirects). Forcing those into
useNitroEventState would lose information and risk regressions in
behavior the lint won't catch. Adoption should happen organically
when contributors see a clean derive-from-event case, not as a
mechanical replace-all.

https://claude.ai/code/session_01GrR87LAqnAEyKG2ZbmQt5Q
2026-05-11 16:31:52 +00:00
simoleo89 535fa71020 ESLint --fix: auto-fix brace-style, indent, semi, no-trailing-spaces
Run eslint --fix across src/ to clear ~1900 mechanical lint errors
surfaced by the @typescript-eslint v8 + react-hooks v7 + react-compiler
upgrade in the React 19 modernization PR.

Issues fixed automatically:
- brace-style (Allman): try/catch one-liners reformatted to multi-line
- indent: tab-vs-space and depth corrections
- semi: missing trailing semicolons
- no-trailing-spaces

No semantic changes. Remaining 701 errors are real-code issues
(set-state-in-effect, rules-of-hooks, no-unsafe-* type checks) that
need manual per-file review.

https://claude.ai/code/session_01GrR87LAqnAEyKG2ZbmQt5Q
2026-05-11 16:31:50 +00:00
duckietm d88defb4a5 🆙 Fixed the commands 2026-05-08 16:44:45 +02:00
Lorenzune 57b83c1097 Refine mobile avatar widgets and login flow 2026-05-07 21:19:15 +02:00
Lorenzune 541d3045f1 Update secure login flow and login view 2026-04-23 16:26:32 +02:00
Lorenzune 726d1cc5c8 Merge latest duckie main with login UI 2026-04-21 11:53:30 +02:00
Lorenzune 58e0ed30f6 Merge remote-tracking branch 'duckie-temp/main' into duckie-merge-2026-04-21
# Conflicts:
#	src/components/room/widgets/chat-input/ChatInputView.tsx
#	src/components/toolbar/ToolbarView.tsx
#	src/css/chat/Chats.css
#	src/css/nitrocard/NitroCardView.css
#	src/css/purse/PurseView.css
#	src/css/room/RoomWidgets.css
2026-04-21 11:19:59 +02:00
Lorenzune 9b36513def WIP preserve local changes before duckie merge 2026-04-21 11:13:32 +02:00
duckietm d3e6743fdf 🆙 Do not make have_offer static 2026-04-17 14:23:26 +02:00
duckietm 88117d937f 🆙 Fix Catalog editor 2026-04-17 13:51:46 +02:00
duckietm b0967d7eaf 🆕 New Misc clothing 2026-04-16 13:34:53 +02:00
DuckieTM bae6f58b10 Merge branch 'Dev' into feat/wired-fixes-apr08 2026-04-13 16:58:14 +02:00
duckietm bef58bc929 🆙 Cleanup old youtube link in chat, now broadcasting is working 2026-04-10 16:32:14 +02:00
duckietm e7cf7809bc 🆙 Memory usage fixes 2026-04-10 11:40:39 +02:00
duckietm c7348a9509 Stage 2 Youtube & upgrade to vite 8 2026-04-09 15:35:58 +02:00
duckietm bbd4ccf30c 🆙 Stage 1 Youtube broadcast 2026-04-09 11:54:57 +02:00
Lorenzune 5e9e3e1e4c Polish wired editor UI and variable handling 2026-04-08 16:18:16 +02:00
duckietm 5bff312b3b 🆙 Fixed some minor bugs 2026-04-08 14:06:25 +02:00
Lorenzune 954e477e47 feat: add builders club catalog ui flow 2026-04-07 14:40:51 +02:00
Life 0b033742d0 Fix badge notification: single bubble, working Wear button
Block NotificationDialogMessageEvent badge types to prevent duplicate
bubbles. Wrap bubble content in stopPropagation div so button clicks
don't close the notification before toggleBadge runs. Request badge
data on mount so Wear works even if inventory was never opened.
2026-04-04 21:25:46 +02:00
Life bc6a33a3ba Deduplicate badge notifications from Achievement and BadgeReceived events
Both events fire for the same badge, causing two notifications. Track
recently notified badge codes in a Set so only the first event shows
the notification bubble, the second is silently skipped.
2026-04-04 21:25:45 +02:00
Life c9e7461714 Dynamic badge slots from config, double-click remove, direct wear from toast
Read user.badges.max.slots from config instead of hardcoded 5. InfoStand
layout adapts: 5 slots shows group badge, 6 slots replaces group with
6th badge. Double-click on InfoStand badge removes it. Badge received
toast now directly equips the badge via toggleBadge and closes.
2026-04-04 21:25:45 +02:00
Life 020db83870 Add golden glow for new badges and badge received toast notification
New unseen badges pulse with a gold glow instead of a flat green
background. When a badge is received, a bubble notification appears
with the badge image, name, and a "Wear" button that opens inventory.
2026-04-04 21:25:16 +02:00
Life 73ee9c7603 Badge DnD rework: fix duplicate/disappearing badges, add visual feedback
Fix slot 0 drag bug ('0' is falsy), prevent badge duplication from stale
props fallback in InfoStand, add sparse slot support, fix race condition
with pending server updates. Add drag preview, glow animations, drop
settle effect, and remove-badge indicator overlay.
2026-04-04 21:25:03 +02:00
Lorenzune c4e1318fd5 fix: polish furniture widgets and area hide toggle 2026-04-03 13:00:05 +02:00
Lorenzune e4b1f14fa2 feat: update room control widgets and menus 2026-04-03 12:09:16 +02:00
Lorenzune 21193daebb Merge upstream/main into feature/checkpoint-20260403 2026-04-03 05:26:19 +02:00
Lorenzune 36c0221a54 chore: checkpoint current work 2026-04-03 05:22:26 +02:00
Lorenzune 83540ff329 feat: add advanced wired variable tools UI 2026-04-02 04:44:04 +02:00
duckietm 6609c0325f 🆙 Fix Youtube TV's 2026-03-31 11:41:21 +02:00
Life a5a7215e09 Change pendingActionRef to hold action and itemId
Refactor pendingActionRef to store action and itemId as an object instead of a string.
2026-03-30 17:55:11 +02:00
Life c4d948cd3a feat: FurniEditor WebSocket — full UI with toolbar icon, infostand button, Edit/Search views, Tailwind styling 2026-03-28 08:52:59 +01:00
duckietm bbe71e9753 🆙 Cleanup Furni-Edit & Fix the avatar-editor 2026-03-27 13:38:03 +01:00
duckietm 7c39dcb513 🆙 Small fixes NFT Clothing 2026-03-26 16:29:27 +01:00
Lorenzune 3b3e91f6d9 Add NFT avatar tab and wired extras UI 2026-03-26 05:24:53 +01:00
duckietm 303b75d378 🆕 🐶 have you favorite pet as your best pall next to you 2026-03-25 14:11:53 +01:00
duckietm df1437c488 🆙 Cleanup 2026-03-24 11:56:51 +01:00
DuckieTM 4aef7d5f94 Merge branch 'main' into chat-prefix 2026-03-24 10:54:42 +01:00
duckietm 33c31fe07d 🆕 Added New catalogue page 2026-03-23 15:02:20 +01:00
duckietm accb69d6c9 🆙 Reverting furnieditor 2026-03-23 12:00:31 +01:00
duckietm a0d0b5c4a4 Revert "Merge branch 'main' into furnisettingeditor-pr"
This reverts commit dfbfb1c2c1, reversing
changes made to 07702c44d0.
2026-03-23 11:49:05 +01:00
DuckieTM dfbfb1c2c1 Merge branch 'main' into furnisettingeditor-pr 2026-03-23 11:13:00 +01:00
DuckieTM 735be2aff6 Merge branch 'main' into catalog-redesign 2026-03-23 08:49:20 +01:00
DuckieTM b73c0841f2 Merge pull request #40 from Lorenzune/feature/wired-movement-source-fixes
feat: update wired editor extras and selection handling
2026-03-22 21:26:53 +01:00
Life da791cd0d0 0 2026-03-22 20:40:05 +01:00
Life 07702c44d0 feat(furni-editor): migrate to WebSocket communication and improve UI
Migrate the Furni Editor from REST API to WebSocket-based communication
using custom packet handlers (10040-10046). The editor now communicates
directly with the emulator for all CRUD operations on furniture items.

Key changes:
- Replace REST API calls with WebSocket composers/parsers for search,
  edit, create, and delete operations
- Read furnituredata.json path from renderer-config.json for asset
  management
- Improve search UI with larger fonts, better contrast, and click-to-copy
  ID functionality with toast notification
- Compact edit view layout with collapsible sections and visual dividers
- Remove unused Create tab (creation handled via edit workflow)
- Add isModerator guard for admin-only access
- Support search by ID, name, or sprite ID with type filtering
2026-03-22 17:57:27 +01:00
Life a5ea88010e feat: catalog style toggle (classic/new) with admin mode & favorites 2026-03-22 16:54:40 +01:00
Lorenzune 3e20f65f3a feat: update wired editor extras and selection handling 2026-03-22 16:48:51 +01:00