Commit Graph

89 Commits

Author SHA1 Message Date
simoleo89 a33bbb3448 feat(radio): make the radio widget toggleable from ui-config
Move the radio on/off switch out of renderer-config (where it sat next
to asset/data URLs) into ui-config, alongside the other UI feature
toggles (game.center.enabled, guides.enabled, …) — the natural home for
a widget switch — and rename it to the dotted convention `radio_ui.enabled`.

The MainView gate now defaults to `false`, so the radio is opt-in: an
absent key keeps it hidden; set `"radio_ui.enabled": true` in ui-config
to show it. The radio.url data source stays in renderer-config.
2026-05-31 09:34:25 +02:00
medievalshell 91f114bb3d fix(config): pet.asset.url usa /pet/ non /pets/ (cartella bundled e 'pet') 2026-05-30 02:02:43 +02:00
medievalshell dc0a8f965e feat(catalog): toggle stile catalogo classico/moderno
Aggiunge un checkbox nelle impostazioni utente per scegliere lo stile del
catalogo (classico vs moderno) + flag globale catalog.classic.style in
ui-config.json come default per tutti. Override per-utente in localStorage.
2026-05-29 23:36:06 +02:00
duckietm d0c11f047a 🆙 Complete rebuild of toolbar / catalog / inventory make it 100% mobile friendly Take #1 2026-05-29 11:30:17 +02:00
duckietm 47e8338570 🆙 Wheel of prizes ! 2026-05-28 16:27:48 +02:00
duckietm 06b8fda1c9 🆙 Enable or disable the radio 2026-05-28 15:52:29 +02:00
duckietm bade7e2623 🆙 Update texts to use JSON5 and added all text 2026-05-28 15:25:27 +02:00
medievalshell acb3dd7ef1 feat: hotel radio widget (client-side, multi-station)
Adds a compact collapsible radio widget (top-left) that plays internet
radio streams with the HTML5 Audio API — no server/renderer changes.

- station list loaded from a JSON5 config file (loadGamedata: JSON + JSON5),
  shipped as radio-stations.json5.example so each hotel fills in its own
- shows the selected station + a dropdown (3 visible, scrolls if more) to
  switch; volume slider; animated equalizer + LIVE indicator
- first station autostarts quietly (5%) on load, with a resume-on-first-
  gesture fallback for browser autoplay policy
2026-05-28 10:20:15 +02:00
medievalshell 4833ab8447 feat: soundboard pads can load from a JSON5 file (DB fallback)
When the server (soundboard_sounds table) returns no pads, the client now
loads them from a JSON5 config file (loadGamedata accepts plain JSON and
JSON5). Useful when the DB / CMS isn't set up yet.

File-defined pads play locally for the clicker; DB-backed pads still go
through the server broadcast so everyone in the room hears them. Ships a
radio-style soundboard-sounds.json5.example template.
2026-05-28 10:19:16 +02:00
medievalshell 7a65e5bf6d feat: soundboard (room-scoped custom audio pads)
Client side of the soundboard. Room owners enable it in Room Settings >
Misc (next to the YouTube TV toggle). When enabled, a soundboard icon
appears in the toolbar for everyone in the room; pressing a pad broadcasts
the sound so all occupants hear it. Incoming SoundboardPlay is played via
the HTML5 Audio API.

Also: fix FloorplanCanvasSVG to use ReactElement instead of the removed
global JSX namespace (React 19), and pair the client Dev branch with the
renderer fork that carries the custom features in CI.

How sounds are managed (works with any CMS):
Sounds are rows in the `soundboard_sounds` table:
    id, name, url, enabled, sort_order
The emulator loads every row with enabled=1 (ordered by sort_order, id)
and sends the list to clients on room enter; the client plays `url`
directly, so any publicly reachable audio URL works (mp3/ogg/wav).

To add a sound from an admin/housekeeping panel of any CMS:
  1. Upload the audio file to wherever the CMS stores public assets
     (same approach as custom badge images).
  2. INSERT a row into `soundboard_sounds` with the display name and the
     public URL of the uploaded file, enabled = 1.
  3. Reload the emulator soundboard (or restart) to pick it up.
Relative urls resolve against the `soundboard.url.prefix` config key
(falls back to `asset.url`); absolute urls are used as-is.
2026-05-28 09:04:17 +02:00
medievalshell 61aceaa422 feat: rare values panel + fortune wheel UI + prize editor
Toolbar buttons, FortuneWheelView (animated wheel, prize icons, recent winners),
RareValuesView (diamond price guide + staff prize-editor tab), furni infostand
value line, useFortuneWheel/useRareValues hooks, it/en text examples.
2026-05-28 02:39:02 +02:00
duckietm 11702fa5e0 🆙 Small updates for the HK 2026-05-26 12:51:33 +02:00
simoleo89 b8675b9dc3 feat(hk): reveal-and-copy card for reset password (+ catalog cleanup)
Two things in one commit because they sit on top of each other:

1. **Reset password reveal card.** The emulator's
   `HousekeepingResetUserPasswordEvent` already returns the freshly
   generated 12-char plaintext in the action-result `message`, but
   the client was leaking it through the standard success-banner
   pipeline — auto-dismiss in 4s, truncated, no copy button. Operators
   were missing it.

   - New `<HousekeepingPasswordReveal />` card mounted in the panel
     header (between the status banner and tab content). Stays put
     until manually dismissed.
   - `useHousekeepingStore` gains a dedicated `passwordReveal` slot
     (`{ userId, username, password }`) plus `revealPassword()` /
     `clearPasswordReveal()` setters. Sensitive data, kept OUT of the
     generic banner / toast pipeline.
   - `useHousekeepingActions.resetUserPassword` no longer routes
     through `wrap()` — it intercepts the result, lifts the
     plaintext into the reveal slot, and uses a localizable success
     key (`housekeeping.action.reset_password.done`) for the banner so
     the password itself never lands there.
   - Copy button uses `navigator.clipboard.writeText` in secure
     contexts with a `document.execCommand('copy')` fallback for
     http:// deployments. Confirmation icon flips to a checkmark for
     ~1.6s on success. The input is `select-all` + auto-select on
     focus so Ctrl+C is also a manual fallback.
   - 8 new i18n keys (EN + IT, .example + runtime UITexts.json5 /
     UITexts.en.json5).

2. **Catalog admin cleanup ported from the PR branch.** The dev
   branch was still carrying the catalog admin code (handlers, hooks,
   store slots, i18n keys) even though the local renderer is on the
   catalog-stripped `feat/housekeeping-packets` branch — typecheck
   was breaking because the catalog composers no longer exist on the
   linked renderer. Stripped here to match: 4 catalog actions
   removed from `HousekeepingActionType`, `HousekeepingApi.ts`,
   `useHousekeepingActions`, `useHousekeepingStore`. The CATALOG tab
   id is gone from `HousekeepingTabId`. Catalog interfaces
   (`IHousekeepingCatalogPage` / `IHousekeepingCatalogOffer`) are
   dropped. 17 catalog i18n keys removed per locale. Two test files
   updated to match.
2026-05-24 16:56:39 +02:00
simoleo89 eeab548917 feat(housekeeping): in-client admin panel
Adds the Housekeeping in-client admin panel — a Modtools-adjacent
surface that runs entirely inside the React client, talking to the
emulator over the existing wire instead of a separate REST/CMS layer.

Surface:
- `src/components/housekeeping/` — panel shell + 5 tabs (Dashboard,
  Users, Rooms, Economy, Audit). Each tab drives one domain of the
  matching emulator handlers (find/sanction/admin/economy/catalog/
  hotel-wide).
- `src/api/housekeeping/` — composer/parser orchestration:
  `HousekeepingApi.ts` exposes 30+ typed actions, each one running
  through `runHkAction()` which awaits the shared
  `HousekeepingActionResultEvent` correlated by action key.
- `src/hooks/housekeeping/` — `useHousekeeping` (the public hook),
  `useHousekeepingStore` (useBetween singleton: shared selection +
  audit polling + sanction templates), `useHousekeepingActions`,
  `useHousekeepingConfirm`.
- `src/api/nitro/awaitMessageEvent.ts` — Promise adapter over
  `CommunicationManager.subscribeMessage` with a sync `select`
  callback that snapshots the parser INSIDE the subscribe handler
  before the renderer recycles the parser instance after the
  Promise resolves.
- `public/configuration/housekeeping-texts-{en,it}.example` —
  149 EN + 149 IT i18n keys under `housekeeping.*` for every panel
  string + every server-side error slug the emulator may emit.

Wiring (additive only):
- `src/components/MainView.tsx` — `<HousekeepingView />` mounted
  alongside `<ModToolsView />`.
- `src/api/index.ts`, `src/hooks/index.ts`, `src/api/nitro/index.ts`
  — added the `housekeeping` and `awaitMessageEvent` re-exports.

Wire contract: pairs against the Arcturus PR (#120 on
duckietm/Arcturus-Morningstar-Extended) and the renderer PR (#77 on
duckietm/Nitro_Render_V3). Incoming events 9100..9129, outgoing
composers 9200..9207. Permission gate `acc_housekeeping` enforced
server-side; the panel is hidden client-side via
`housekeeping.enabled` in the runtime ui-config.
2026-05-24 16:38:16 +02:00
duckietm 49917ed49b 🆕 Redesign of HC Club buy, now also give as gift 2026-05-21 14:00:03 +02:00
duckietm 690a196d42 🆙 Fix texts 2026-05-21 08:59:26 +02:00
DuckieTM e9591acc0e Merge pull request #146 from medievalshell/Dev
feat(loading): redesigned loader with progress bar, task labels, configurable assets + perf(build): granular code-split + preconnect hint for cold-load speed + docs: PERFORMANCE.md — client + server recipe for the 4s cold load
2026-05-21 07:39:32 +02:00
medievalshell c685c997a3 feat(loading): redesigned loader with progress bar, task labels, configurable assets
Loading screen overhaul:
- LoadingView: Nitro V3 logo flush top-left, loading.gif at viewport
  centre, large progress bar (max 900px / 90vw, h-8, gradient + glow)
  anchored bottom-centre with the percentage rendered inside the bar in
  Poppins, plus a friendly stage label underneath. Logo + background +
  progress bar colour overridable via renderer-config keys
  (loading.logo.url, loading.background, loading.progress.color).
- App.tsx: wired a real loadingProgress (0->100) + loadingTask driven by
  the boot pipeline: config init (10), renderer (20), per-warmup-task
  bumps for AssetManager/Localization/AvatarRender/SoundManager (25->70),
  session managers (78/85/92), Communication (98), ready (100). Each bump
  carries a task label looked up via a new taskLabel(key, fallback)
  helper so the Italian baseline ("Sto caricando il guardaroba",
  "Connessione al server", ...) can be translated by editing
  renderer-config; fallback keeps current strings if the key is missing.
- AvatarEffectsView: replace raw fetch(url).json() with
  loadGamedata(url) so the effectmap root manifest (JSON5 with
  // comments) parses correctly and supports the core/custom/seasonal
  tier merge.
- fallbackToLogin: respect login.screen.enabled=false. When login is
  disabled (SSO-only deployments), init failures now route to
  showSessionExpired() (home + diagnostic) instead of rendering an empty
  LoginView placeholder.
- scripts/write-asset-loader.mjs: the pre-React shell rendered into
  #root before the JS bundle takes over was a light-blue login skeleton
  (linear gradient + two grey rectangles) producing a visible flash
  before the real loader appeared. Replaced with the same
  radial-gradient the LoadingView paints — the handoff is now invisible.
- renderer-config.example: document the 13 loader keys so operators can
  copy & translate.
2026-05-21 00:22:17 +02:00
simoleo89 0ad284fa9c refactor(mod-tools): drop the launcher Context strip
The Context strip at the top of the launcher showed which room the
mod is currently observing — green pill + door icon when in a room,
zinc strip when not. In practice it's noise: the Room Tool / Chatlog
Tool buttons right under it already gate on the same in-room state
(disabled when not in a room) and carry their own tooltip explaining
that. The strip duplicated the signal without adding actionable info.

Remove the section, the now-unused FaDoorOpen / FaDoorClosed imports,
and the matching `modtools.window.section.context` /
`modtools.window.context.room` locale keys (from both the runtime
UITexts.json and the versioned UITexts.example template).
2026-05-20 22:01:58 +02:00
simoleo89 91938985a2 refactor(mod-tools): launcher box gets context strip + section grouping
The launcher panel was a flat stack of four buttons (Room Tool, Chatlog
Tool, selected-user + presence dot inline, Report Tool) with no visual
hierarchy. The selected-user row was particularly cramped — name, the
2px dot and the 4×4 close-X all crammed into a single button row, easy
to misclick.

Reorganize into four logical groups, each with a small uppercase
section label:

  Context  — gradient strip (emerald when in a room, zinc when not)
             showing "Room #<id>" or "Enter a room first" with a
             matching door icon. Source of truth for "what is the
             mod observing right now"; both Room Tool and Chatlog
             Tool feed from the same currentRoomId.

  Room     — Room Tool + Chatlog Tool stacked. Both still gate on
             isInRoom; the disabled state now reads from a single
             flag instead of repeating `currentRoomId <= 0`.

  User     — When a user is selected: a card with the presence dot
             (emerald = still in room, zinc = left), the username at
             a real legible size, a bigger close button, plus a
             dedicated "Open Info" button to toggle ModToolsUserView.
             Splitting the click target from the close action removes
             the misclick footgun.
             When no user is selected: a dashed-border empty state
             with a FaUserSlash icon and the "Select a user" hint —
             reads as a clear "no selection" instead of an active
             button you can't press.

  Reports  — Report Tool with the open-ticket badge. Badge gets a 2px
             rose halo box-shadow so a new ticket pulses into view
             instead of competing with the button background.

Locale keys added under modtools.window.section.* and
modtools.window.context.room / modtools.window.user.open_info, in both
the runtime UITexts.json and the versioned UITexts.example template.

The "Open Info" button label is a fix in flight — the old layout
overloaded the username row to also open user info, with no separate
label. The new explicit button gets its own key so the action is
unambiguous (the previous version mislabelled the button as "Mod
Action", which is actually a different sub-panel).

typecheck + vitest 214/214 + JSON validation all clean.
2026-05-20 21:41:52 +02:00
simoleo89 75815fa022 i18n(mod-tools): route every label/title/placeholder through LocalizeText
The ModTools template refresh introduced ~80 hardcoded English strings
(labels, placeholders, tooltips, empty-state copy, button text). Move
every one of them onto the modtools.* namespace and read via
LocalizeText so the panels translate alongside the rest of the client.

UITexts.example (versioned template) extended with the full set:

  modtools.window.*            Launcher box (toolbar item, tools,
                               selected-user state, ticket count)
  modtools.userinfo.*          User info card — already had the
                               legacy modtools.userinfo.{userName,
                               cfhCount, …} keys from before; added
                               refresh tooltip, presence pill labels
                               (in_room / online / offline with
                               matching .title tooltips), section
                               headings, action button labels, stat
                               card labels
  modtools.roominfo.*          Room info card — title, refresh, loading,
                               owner pill (here/away + tooltips), stat
                               labels, action buttons, moderate panel
                               heading + checkboxes + textarea
                               placeholder + caution/alert CTAs
  modtools.user.message.*      Send-message dialog (recipient label,
                               body label, placeholder, char counter,
                               empty state, send button)
  modtools.user.modaction.*    Mod Action form — header, sanctioning
                               label, 3-step section titles, select
                               placeholders, message label + optional
                               note, message placeholder, preview
                               heading, default/apply buttons, every
                               sendAlert error message
  modtools.user.visits.*       Room visits — title, header strip
                               heading, entry count (singular/plural),
                               empty state, column headers, visit
                               button + tooltip
  modtools.user.chatlog.*      User chatlog — title (with username
                               variant), loading state
  modtools.room.chatlog.*      Room chatlog title
  modtools.chatlog.*           Shared ChatlogView — column headers,
                               empty state, room-separator Visit/Tools
                               buttons
  modtools.tickets.*           Tickets window — title, tab labels
                               (open/mine/picked), column headers,
                               empty states, action buttons (pick/
                               handle/release), issue resolution
                               window (title, label, details heading,
                               field labels, chatlog toggle, resolve-as
                               heading, resolution buttons, release
                               back to queue), CFH chatlog title

The same 130 entries land in Nitro-Files/.../UITexts.json (runtime).
Both files validate as JSON. The runtime additions take effect on
next client reload; the template additions ship the strings to any
fresh deploy.

Notes:
  - The MOD_ACTION_DEFINITIONS sanction names ("Alert", "Mute 1h",
    "Ban 18h" …) stay hardcoded for now since they're keyed off
    server-side action IDs that don't have an existing locale key
    convention. Worth a follow-up if needed.
  - help.cfh.topic.* keys (CFH topic display names) are already in
    ExternalTexts.json and were already read via LocalizeText, so
    they didn't need changes.

typecheck + vitest 214/214 + lint:hooks all clean.
2026-05-20 21:41:52 +02:00
duckietm 0d935a15c1 🆙 Update for the render-config 2026-05-20 13:50:27 +02:00
Lorenzune 4e1ceed53f Add badge leaderboard UI and badge rarity styling 2026-05-19 15:30:47 +02:00
medievalshell 2fded7bc79 feat: interactive JSON / JSON5 mode selector at build time
Lets the operator pick between strict JSON (legacy) and JSON5 for every
configuration file consumed by Nitro and the renderer.

- scripts/configure-json.mjs: interactive prompt (JSON5 recommended),
  with --if-missing and --non-interactive flags for CI use
- package.json: yarn configure / prestart / prebuild hooks
- vite.config.mjs: reads .nitro-build.json (or NITRO_JSON_MODE env) and
  injects the compile-time constant __NITRO_JSON_MODE__ via define
- src/bootstrap.ts: routes client-mode.json parsing through the
  selected mode
- .gitignore: ignore the per-deployment .nitro-build.json
- README: full usage and override section
- public/configuration assets regenerated by the updated prebuild flow

The renderer side (@nitrots/utils JsonParser) is updated in the
companion Nitro_Render_V3 commit on the dev branch.
2026-05-18 20:38:26 +02:00
DuckieTM e209146f47 🆙 Update About screen (needs a emu change as well) 2026-05-17 09:58:38 +02:00
duckietm 6124610736 🆙 Small fix Avatar loading & moved news to path wich you can enter
The example data has been provided in /Content-Gamedata so you could place it in /gamadata or anything you like.
Do not forget the render-config.json to update :

"login.health.method": "GET",
"login.news.url": "${asset.url}/news/news.json",
2026-05-08 11:58:32 +02:00
DuckieTM 71725b7f67 Merge branch 'Dev' into merge-duckie-main-2026-05-06 2026-05-08 07:45:17 +02:00
Lorenzune 57b83c1097 Refine mobile avatar widgets and login flow 2026-05-07 21:19:15 +02:00
duckietm dbf5ae875c 🆙 Small update in building 2026-05-06 12:50:00 +02:00
duckietm f6b7a3c9d7 🆙 Update Render example 2026-05-06 10:38:55 +02:00
duckietm aa20b0acbe 🆙 Small fix Background to load from json 2026-05-06 08:57:44 +02:00
Lorenzune 851d82f93f Document secure runtime configuration 2026-05-06 06:27:40 +02:00
Lorenzune 71171dc205 Merge remote-tracking branch 'duckie/main' into merge-duckie-main-2026-05-06
# Conflicts:
#	index.html
#	public/UITexts.example
#	public/renderer-config.example
#	src/App.tsx
#	src/components/login/LoginView.tsx
#	src/components/room/widgets/avatar-info/infostand/InfoStandWidgetUserView.tsx
#	src/components/toolbar/ToolbarView.tsx
#	src/components/user-profile/UserContainerView.tsx
2026-05-06 04:23:15 +02:00
duckietm 6fce62fb47 🆙 Updated Background profiles
Please make sure you change your UI-Config !!!
2026-05-04 15:26:29 +02:00
simoleo89 72bc4da3c0 feat(profile): add full-box card background tab and rendering
Adds a "Cards" tab to the Profile Background picker (BackgroundsView)
that selects a pattern applied to the entire user info card and the
extended profile container, in addition to the existing avatar-pad
background/stand/overlay layers.

- AvatarInfoUser/Utilities: propagate cardBackgroundId from RoomUserData.
- InfoStandWidgetUserView: stateful cardBackgroundId, applied as
  .profile-card-background.card-background-{id} on the outer Column
  with bg-color suppressed when active.
- UserContainerView: same class on the wrapper of the extended profile.
- BackgroundsView: 4th tab "cards" backed by cards.data config
  (falls back to backgrounds.data); sends 4-id message via the
  extended sendBackgroundMessage signature.
- ui-config.example: cards.data dataset (15 entries).
- BackgroundsView.css: 188 .card-background-{N} rules cloned from
  background-{N} (repeat-tiled) plus 15 CSS-pattern overrides for the
  provisional dataset (gradients, stripes, dots, grid, checker).
2026-05-03 22:09:12 +02:00
duckietm 506a29c9a0 🆕 Create Custom Bage & Security update 2026-05-01 16:02:56 +02:00
duckietm 46eb7b45fc 🆙 Code cleanup News UI Login 2026-05-01 07:47:12 +02:00
duckietm eb0bf80dfa 🆙 Fix the avatar-editor faces 2026-04-29 15:44:17 +02:00
Lorenzune 3c9a599505 Add secure configuration bootstrap flow 2026-04-25 13:29:48 +02:00
duckietm e5705e55db 🆙 Added CryptoV2 2026-04-24 16:32:56 +02:00
Lorenzune 6c7d78c156 Move runtime URLs to config examples 2026-04-24 16:12:04 +02:00
Lorenzune 21dd357397 Replace production domain references with examples 2026-04-24 15:59:55 +02:00
Lorenzune 42731218f8 Add runtime toggle docs and secure mode switches 2026-04-24 15:53:17 +02:00
Lorenzune 541d3045f1 Update secure login flow and login view 2026-04-23 16:26:32 +02:00
duckietm ce24e8a904 🆙 Update renderer-config when crypto can be enabled 2026-04-23 16:00:33 +02:00
duckietm 969f4a07d2 🆕 Token login added
Backend (AuthHttpHandler):
- New users_remember_tokens table stores sha256 hex of the raw token
  so the DB never holds a usable credential. Seed file adds the table
  and a login.remember.duration.days setting (default 30).
- /api/auth/login accepts "remember": true. On success, issues a fresh
  32-byte base64url token, stores the hash, returns the raw token.
- New POST /api/auth/remember: accepts the raw token, looks up by hash,
  on a valid hit mints a fresh SSO ticket, rotates the token (deletes
  the consumed one and issues a new one), returns both to the client.
  No Turnstile - it's an automated trusted-device flow.
- /api/auth/logout also accepts rememberToken and deletes that single
  row so other devices keep their tokens.

Frontend:
- LoginView: "Remember me" checkbox (key login.remember_me already in
  ExternalTexts). Enabling it persists the returned rememberToken in
  localStorage.nitro.remember.token.
- App.tsx: before deciding to show the login screen, try a silent POST
  to /api/auth/remember with the stored token. On 200, inject the
  returned ssoTicket into window.NitroConfig and proceed to the
  authenticated flow; on 401, forget the token and show login.
- PurseView logout: sends the stored rememberToken in the body so the
  server can delete it, and clears localStorage before reload.
2026-04-23 10:16:32 +02:00
duckietm 2ff37c22d2 🆙 Added the use of ExternalTexts / UITexts 2026-04-23 08:33:04 +02:00
Lorenzune 237c523f9a checkpoint: secure assets and login flow baseline 2026-04-23 07:01:09 +02:00
duckietm f6096371be 🆙 Updated Register user for internal Client
Make sure you have the hotlooks.json in the /dist folder !
2026-04-22 09:49:35 +02:00
duckietm 947b83a0ed 🆙 Updated Register user for internal Client
Make sure you have the hotlooks.json in the /dist folder !
2026-04-22 07:58:30 +02:00