From 487666eed80987efbc745e1c77c37efe81ccc868 Mon Sep 17 00:00:00 2001 From: legop3 Date: Wed, 16 Sep 2026 14:45:09 -0400 Subject: [PATCH] rename old room controls to lights and rename new thing to activity controls --- server/src/rewards/definitions/lightStrobe.js | 2 +- server/src/services/greenModeService/index.js | 4 ++-- .../homeAssistantActivitiesService/actions.js | 2 +- .../activities.test.js | 3 ++- .../configuration.js | 12 ++++++------ .../homeAssistantActivitiesService/locks.js | 2 +- .../homeAssistantService/configuration.js | 4 ++-- .../src/services/homeAssistantService/hooks.js | 8 ++++---- server/src/services/idleService/actions.js | 2 +- .../operatorCommandService/commands/ha.js | 4 ++-- .../services/operatorCommandService/registry.js | 2 +- .../GamepadMappingSettings/constants.js | 4 ++-- .../HomeAssistantActivitiesPanel/index.jsx | 2 +- .../components/HomeAssistantControls/index.jsx | 16 ++++++++-------- webui/src/components/KeymapSettings/index.jsx | 4 ++-- webui/src/components/PtzCamera/index.jsx | 6 +++--- webui/src/controls/ControlContext.jsx | 2 +- .../src/controls/inputs/KeyboardInputManager.jsx | 2 +- webui/src/help/content.js | 10 +++++----- webui/src/layouts/driver/MobileTabs/index.jsx | 2 +- .../driver/tabs/mobile/RoomControlsTab/index.jsx | 2 +- 21 files changed, 48 insertions(+), 47 deletions(-) diff --git a/server/src/rewards/definitions/lightStrobe.js b/server/src/rewards/definitions/lightStrobe.js index 475d0f09..7b7a7cdd 100644 --- a/server/src/rewards/definitions/lightStrobe.js +++ b/server/src/rewards/definitions/lightStrobe.js @@ -44,7 +44,7 @@ module.exports = { goal: 400, async run(ctx) { startStrobe(ctx, { endsAt: Date.now() + STROBE_MS, on: false }); - ctx.sendAlert({ color: '#ffc107', title: 'Light Strobe', message: 'All room controls strobing for 60 seconds.' }); + ctx.sendAlert({ color: '#ffc107', title: 'Light Strobe', message: 'All room lights strobing for 60 seconds.' }); }, async recover(ctx, effect) { if (!effect || Number(effect.endsAt || 0) <= Date.now()) { diff --git a/server/src/services/greenModeService/index.js b/server/src/services/greenModeService/index.js index 4effbbaf..7452e44e 100644 --- a/server/src/services/greenModeService/index.js +++ b/server/src/services/greenModeService/index.js @@ -52,7 +52,7 @@ async function setEnabled(nextValue, options = {}) { .map(({ result, entityId }) => ({ entityId, error: result.reason?.message || 'unknown error' })); if (failures.length) { - logger.warn('Some room controls failed to enter green mode', { failures }); + logger.warn('Some room lights failed to enter green mode', { failures }); } } else if (!next && homeAssistantService.enabled) { // Disabling the visual mode simply releases the lock it created. Bulb @@ -67,7 +67,7 @@ async function setEnabled(nextValue, options = {}) { skipping the physical-room operations still allows the session theme, CardFrame styling, alerts, commands, and timed reward to work normally. The integration's generic lock state is also left untouched because there - are no server-managed room controls to lock. + are no server-managed room lights to lock. */ enabled = next; diff --git a/server/src/services/homeAssistantActivitiesService/actions.js b/server/src/services/homeAssistantActivitiesService/actions.js index 475139d7..b86d6d8b 100644 --- a/server/src/services/homeAssistantActivitiesService/actions.js +++ b/server/src/services/homeAssistantActivitiesService/actions.js @@ -12,7 +12,7 @@ function createActions({ getConfig, ha, locks }) { async function execute(id, value, actor, idle = false) { if (!idle) assertAccess(actor); const config = getConfig(); - if (!config.enabled) throw new Error('Home Assistant activities are disabled'); + if (!config.enabled) throw new Error('Activity Controls are disabled'); const item = config.items.find((entry) => entry.id === id); if (!item) throw new Error('Unknown activity item'); if (!idle && locks.isLocked(id) && !['admin', 'lockdown'].includes(actor.role)) throw new Error('This item is locked'); diff --git a/server/src/services/homeAssistantActivitiesService/activities.test.js b/server/src/services/homeAssistantActivitiesService/activities.test.js index 787dea9d..1aa9a625 100644 --- a/server/src/services/homeAssistantActivitiesService/activities.test.js +++ b/server/src/services/homeAssistantActivitiesService/activities.test.js @@ -129,7 +129,8 @@ test('locks are process-local and names resolve without guessing', () => { assert.equal(resolveItem(items.slice(0, 1), 'FAN SPEED').id, 'number.fan'); assert.equal(resolveItem(items, 'NUMBER.FAN').id, 'number.fan'); assert.throws(() => resolveItem(items, 'Fan speed'), /number.fan, number.other/); - assert.throws(() => resolveItem(items, 'Fan'), /No activity/); + // Keep the lookup error aligned with the panel name users see when choosing an item. + assert.throws(() => resolveItem(items, 'Fan'), /No activity control/); }); test('command preserves multiword names and exposes lock status', async () => { diff --git a/server/src/services/homeAssistantActivitiesService/configuration.js b/server/src/services/homeAssistantActivitiesService/configuration.js index 67094267..5b151e98 100644 --- a/server/src/services/homeAssistantActivitiesService/configuration.js +++ b/server/src/services/homeAssistantActivitiesService/configuration.js @@ -1,4 +1,4 @@ -// Home Assistant activities have their own catalog so room-light bulk actions +// Activity Controls have their own catalog so room-light bulk actions // never acquire unrelated devices simply because they share a connection. const { strictObject, string, boolean } = require('../../configuration/schemaHelpers'); @@ -7,13 +7,13 @@ module.exports = { feature: true, defaultValue: { enabled: false, items: [] }, schema: strictObject({ - enabled: boolean({ description: 'Shows the separate Activities card using the enabled Home Assistant connection.' }), + enabled: boolean({ description: 'Shows the Activity Controls card in Activities using the enabled Home Assistant connection.' }), items: { type: 'array', - title: 'Activity items', + title: 'Activity control items', description: 'Ordered public entities. Control types and limits come from Home Assistant; unsupported domains are read-only.', items: strictObject({ - id: string({ title: 'Entity id', description: 'Exact Home Assistant entity ID to expose in Activities.', pattern: '^[a-z0-9_]+\\.[a-z0-9_]+$', maxLength: 255, examples: ['input_number.fan_speed'] }), + id: string({ title: 'Entity id', description: 'Exact Home Assistant entity ID to expose in Activity Controls.', pattern: '^[a-z0-9_]+\\.[a-z0-9_]+$', maxLength: 255, examples: ['input_number.fan_speed'] }), name: string({ title: 'Display name', description: 'Optional override; otherwise uses the Home Assistant friendly name.', maxLength: 120, examples: ['Fan speed'] }), icon: string({ description: 'Font Awesome name, as used by social links. Blank or invalid names use a fallback.', maxLength: 80, examples: ['FaFan'] }), // Match social-link colors so admins can customize tiles through the existing config form. @@ -21,7 +21,7 @@ module.exports = { readOnly: boolean({ title: 'Read only', default: false, description: 'Display the value without allowing user or idle commands.' }), idleAction: string({ title: 'When idle', enum: ['unchanged', 'set', 'press'], default: 'unchanged', description: 'Leave unchanged, set the idle value, or press a button once. Runs independently of user locks.' }), idleValue: string({ title: 'Idle value', description: 'For set: on/off, a number, exact selection, or text (empty text clears it). Checked against live entity limits when idle runs.', examples: ['0'], maxLength: 255 }), - }, { description: 'One independently controlled or read-only activity item.', required: ['id'] }), + }, { description: 'One independently controlled or read-only activity control item.', required: ['id'] }), }, - }, { title: 'Home Assistant activities', description: 'Generic activity controls and idle behavior, separate from room lighting.', required: ['enabled', 'items'] }), + }, { title: 'Activity Controls', description: 'Generic activity controls and idle behavior, separate from room lighting.', required: ['enabled', 'items'] }), }; diff --git a/server/src/services/homeAssistantActivitiesService/locks.js b/server/src/services/homeAssistantActivitiesService/locks.js index e0dc5db9..e06db0e1 100644 --- a/server/src/services/homeAssistantActivitiesService/locks.js +++ b/server/src/services/homeAssistantActivitiesService/locks.js @@ -19,7 +19,7 @@ function resolveItem(items, query) { if (idMatch) return idMatch; const matches = items.filter((item) => item.name.toLowerCase() === normalized); if (matches.length > 1) throw new Error(`Name is ambiguous. Use an entity ID: ${matches.map((item) => item.id).join(', ')}`); - if (!matches.length) throw new Error('No activity item matches that name or entity ID'); + if (!matches.length) throw new Error('No activity control item matches that name or entity ID'); return matches[0]; } diff --git a/server/src/services/homeAssistantService/configuration.js b/server/src/services/homeAssistantService/configuration.js index f5efcdfb..9de0aef4 100644 --- a/server/src/services/homeAssistantService/configuration.js +++ b/server/src/services/homeAssistantService/configuration.js @@ -52,14 +52,14 @@ module.exports = { ], }, schema: strictObject({ - enabled: boolean({ description: 'Immediately connects to Home Assistant and enables configured room entities, physical-button triggers, Neato controls, and lift controls.' }), + enabled: boolean({ description: 'Immediately connects to Home Assistant and enables configured room lights, physical-button triggers, Neato controls, and lift controls.' }), url: string({ title: 'Server URL', description: 'Base URL of the Home Assistant server used for its REST and WebSocket APIs.', format: 'uri', maxLength: 2048 }), token: string({ title: 'Long-lived access token', description: 'Home Assistant long-lived access token used to authenticate every API request. The saved value is never returned to the browser.', examples: ['REPLACE_WITH_LONG_LIVED_TOKEN'], writeOnly: true, maxLength: 20000 }), [neato.key]: neato.schema, [lift.key]: lift.schema, entities: { type: 'array', - title: 'Room entities', + title: 'Room Lights', description: 'Home Assistant lights and switches exposed to the room-light controls and button-box actions.', items: strictObject({ id: string({ title: 'Entity id', description: 'Exact Home Assistant entity ID, such as light.rover_room or switch.floor_lamp.', examples: ['light.lab_main'], minLength: 1, maxLength: 255 }), diff --git a/server/src/services/homeAssistantService/hooks.js b/server/src/services/homeAssistantService/hooks.js index a84368d1..fe0bbda8 100644 --- a/server/src/services/homeAssistantService/hooks.js +++ b/server/src/services/homeAssistantService/hooks.js @@ -55,7 +55,7 @@ function registerHomeAssistantHooks(deps) { return cb({ error: 'Insufficient permissions to control Home Assistant' }); } if (isBlockedByRoomControlLock()) { - return cb({ error: 'Room controls are locked' }); + return cb({ error: 'Room lights are locked' }); } try { if (!entityId) throw new Error('entityId required'); @@ -71,7 +71,7 @@ function registerHomeAssistantHooks(deps) { return cb({ error: 'Insufficient permissions to control Home Assistant' }); } if (isBlockedByRoomControlLock()) { - return cb({ error: 'Room controls are locked' }); + return cb({ error: 'Room lights are locked' }); } try { if (!entityId) throw new Error('entityId required'); @@ -87,7 +87,7 @@ function registerHomeAssistantHooks(deps) { return cb({ error: 'Insufficient permissions to control Home Assistant' }); } if (isBlockedByRoomControlLock()) { - return cb({ error: 'Room controls are locked' }); + return cb({ error: 'Room lights are locked' }); } try { if (!entityId) throw new Error('entityId required'); @@ -106,7 +106,7 @@ function registerHomeAssistantHooks(deps) { return cb({ error: 'Insufficient permissions to control Home Assistant' }); } if (isBlockedByRoomControlLock()) { - return cb({ error: 'Room controls are locked' }); + return cb({ error: 'Room lights are locked' }); } try { if (!entityId) throw new Error('entityId required'); diff --git a/server/src/services/idleService/actions.js b/server/src/services/idleService/actions.js index ef72896c..facf753a 100644 --- a/server/src/services/idleService/actions.js +++ b/server/src/services/idleService/actions.js @@ -19,7 +19,7 @@ async function turnOffRoomControls() { const lightPolicy = homeAssistantService.getLightPolicyState?.() || null; const lockState = lightPolicy?.lockState || null; if (lockState === 'on') { - logger.info('Idle room-controls off skipped because room controls are locked on', { + logger.info('Idle room-controls off skipped because room lights are locked on', { lockState, source: 'idleService:turnOffRoomControls', }); diff --git a/server/src/services/operatorCommandService/commands/ha.js b/server/src/services/operatorCommandService/commands/ha.js index 77a8929f..a2b1fa99 100644 --- a/server/src/services/operatorCommandService/commands/ha.js +++ b/server/src/services/operatorCommandService/commands/ha.js @@ -5,12 +5,12 @@ const { getCommandConfig } = require('../config'); function createHaCommand({ homeAssistantActivitiesService: service, config }) { return async function handleHaCommand(message, tokens = []) { const reply = (content) => message.reply({ content, allowedMentions: { parse: [], repliedUser: false } }); - if (!service) return reply('Home Assistant activities are unavailable.'); + if (!service) return reply('Activity Controls are unavailable.'); const action = String(tokens[0] || 'status').toLowerCase(); try { if (action === 'status') { const items = service.getState().items; - return reply(items.length ? items.map((item) => `${item.name} (${item.id}): ${item.locked ? 'locked' : 'unlocked'}`).join('\n') : 'No activity items configured.'); + return reply(items.length ? items.map((item) => `${item.name} (${item.id}): ${item.locked ? 'locked' : 'unlocked'}`).join('\n') : 'No activity control items configured.'); } if (!['lock', 'unlock'].includes(action) || tokens.length < 2) { return reply(`Use ${getCommandConfig(config).prefix} ha status, or ha .`); diff --git a/server/src/services/operatorCommandService/registry.js b/server/src/services/operatorCommandService/registry.js index 2c8f2da8..55866f51 100644 --- a/server/src/services/operatorCommandService/registry.js +++ b/server/src/services/operatorCommandService/registry.js @@ -24,7 +24,7 @@ function buildCommandRegistry(prefix, timeCommand) { // integration is absent. green: { category: 'admin', summary: 'Toggle green room and page mode.', usage: [`${prefix} green `], access: 'Admin', permission: 'admin' }, // Locks are moderation only; entity actions remain in the Activities card. - ha: { category: 'features', summary: 'List activity locks or lock/unlock an item by name or entity ID.', usage: [`${prefix} ha status`, `${prefix} ha `], access: 'Admin', permission: 'admin', requiredFeature: 'homeAssistantActivities', unavailableLabel: 'Home Assistant activities' }, + ha: { category: 'features', summary: 'List activity control locks or lock/unlock an item by name or entity ID.', usage: [`${prefix} ha status`, `${prefix} ha `], access: 'Admin', permission: 'admin', requiredFeature: 'homeAssistantActivities', unavailableLabel: 'Activity Controls' }, lights: { category: 'features', summary: 'Control room lights or manage the admin light lock.', diff --git a/webui/src/components/GamepadMappingSettings/constants.js b/webui/src/components/GamepadMappingSettings/constants.js index 59af90e3..c8791d6c 100644 --- a/webui/src/components/GamepadMappingSettings/constants.js +++ b/webui/src/components/GamepadMappingSettings/constants.js @@ -68,8 +68,8 @@ export const ACTIONS = [ { id: 'videoFilterCycle', label: 'Cycle video filter', kind: 'button', section: 'Camera' }, { id: 'songNoteUp', label: 'Play higher note', kind: 'button', section: 'Audio and chat', driveMode: 'single' }, { id: 'songNoteDown', label: 'Play lower note', kind: 'button', section: 'Audio and chat', driveMode: 'single' }, - { id: 'homeAssistantOn', label: 'Turn next room control on', kind: 'button', section: 'Room controls' }, - { id: 'homeAssistantOff', label: 'Turn next room control off', kind: 'button', section: 'Room controls' }, + { id: 'homeAssistantOn', label: 'Turn next room light on', kind: 'button', section: 'Room lights' }, + { id: 'homeAssistantOff', label: 'Turn next room light off', kind: 'button', section: 'Room lights' }, /* Digital aux actions provide exact parity with the keyboard help surface. They coexist with analog brush controls so each operator can choose proportional triggers or discrete buttons. */ { id: 'auxMainForward', label: 'Main brush forward', kind: 'button', section: 'Aux buttons' }, diff --git a/webui/src/components/HomeAssistantActivitiesPanel/index.jsx b/webui/src/components/HomeAssistantActivitiesPanel/index.jsx index 8ff22f0d..7ded92b7 100644 --- a/webui/src/components/HomeAssistantActivitiesPanel/index.jsx +++ b/webui/src/components/HomeAssistantActivitiesPanel/index.jsx @@ -51,7 +51,7 @@ export default function HomeAssistantActivitiesPanel() { const connected = state.connected && socketConnected; // Reuse the room-control auto-fit grid and compact tile rhythm, while keeping // all data and commands in the Activities namespace on both device layouts. - return {connected ? 'Connected' : 'Offline'}}> {!connected ?

{socketConnected ? 'Home Assistant is offline.' : 'Server disconnected.'} Values may be out of date.

: null} {!allowed ?

Controls are read-only with your current access.

: null} diff --git a/webui/src/components/HomeAssistantControls/index.jsx b/webui/src/components/HomeAssistantControls/index.jsx index f77cc397..aa5cc36e 100644 --- a/webui/src/components/HomeAssistantControls/index.jsx +++ b/webui/src/components/HomeAssistantControls/index.jsx @@ -174,7 +174,7 @@ export default function HomeAssistantControls() { /* Feature existence is owned here, not by each layout that happens to mount - room controls. Disabled integrations render nothing; enabled integrations + room lights. Disabled integrations render nothing; enabled integrations can still show offline/configuration states inside the panel. */ if (!enabled) return null; @@ -199,7 +199,7 @@ function HomeAssistantControlsContent() { if (!ha?.enabled) { return ( - +

Not configured on the server.

); @@ -207,7 +207,7 @@ function HomeAssistantControlsContent() { if (entities.length === 0) { return ( - +

No lights or switches configured.

); @@ -233,16 +233,16 @@ function HomeAssistantControlsContent() { ); return ( - + {lightPolicyLocked ? (

{adminCanControlLockedLights ? lockState === 'off' - ? 'Lights are locked off. Admin room controls remain available.' - : 'Lights are locked on. Admin room controls remain available.' + ? 'Lights are locked off. Admin room lights remain available.' + : 'Lights are locked on. Admin room lights remain available.' : lockState === 'off' - ? 'Lights are locked off. Room controls are disabled.' - : 'Lights are locked on. Room controls are disabled.'} + ? 'Lights are locked off. Room lights are disabled.' + : 'Lights are locked on. Room lights are disabled.'}

) : null} {/* Each lamp declares only the smallest width at which its title, status, diff --git a/webui/src/components/KeymapSettings/index.jsx b/webui/src/components/KeymapSettings/index.jsx index aa000ad3..04648cd1 100644 --- a/webui/src/components/KeymapSettings/index.jsx +++ b/webui/src/components/KeymapSettings/index.jsx @@ -36,8 +36,8 @@ const KEY_ACTIONS = [ { id: 'chatFocus', label: 'Toggle Chat', group: 'Chat' }, { id: 'songNoteUp', label: 'Song Note Up', group: 'Audio' }, { id: 'songNoteDown', label: 'Song Note Down', group: 'Audio' }, - { id: 'homeAssistantOn', label: 'Room Controls On (Cycle)', group: 'Room Controls' }, - { id: 'homeAssistantOff', label: 'Room Controls Off (Cycle)', group: 'Room Controls' }, + { id: 'homeAssistantOn', label: 'Room Lights On (Cycle)', group: 'Room Lights' }, + { id: 'homeAssistantOff', label: 'Room Lights Off (Cycle)', group: 'Room Lights' }, ]; function groupActions(actions) { diff --git a/webui/src/components/PtzCamera/index.jsx b/webui/src/components/PtzCamera/index.jsx index 9b099569..aac487c1 100644 --- a/webui/src/components/PtzCamera/index.jsx +++ b/webui/src/components/PtzCamera/index.jsx @@ -556,7 +556,7 @@ function PtzDesktopFullscreen({ ptz, releasePending }) { {/* - Desktop keeps room controls as the final sidebar tool so camera + Desktop keeps room lights as the final sidebar tool so camera turn controls and replay remain above the less-frequent room-wide actions. HomeAssistantControls owns its own feature and policy gate. */} @@ -604,7 +604,7 @@ function PtzMobileLandscape({ ptz, onClose, releasePending = false }) { {/* The right control column is naturally taller than the viewport. - Placing room controls after the fixed-height video uses that left- + Placing room lights after the fixed-height video uses that left- column space while the whole landscape page continues scrolling as one surface. */} @@ -678,7 +678,7 @@ function PtzMobilePortrait({ ptz, onClose, releasePending = false }) { - {/* Portrait keeps room controls immediately after chat as requested. */} + {/* Portrait keeps room lights immediately after chat as requested. */} diff --git a/webui/src/controls/ControlContext.jsx b/webui/src/controls/ControlContext.jsx index 80e1d8a6..78546e47 100644 --- a/webui/src/controls/ControlContext.jsx +++ b/webui/src/controls/ControlContext.jsx @@ -189,7 +189,7 @@ export function ControlSystemProvider({ children }) { Automatic drive-mode lighting is convenience behavior for the open room. A room-light lock is an explicit policy decision, including locked-off, so this helper must not issue any Home Assistant commands while that - policy is active. Admins can still use the dedicated room controls when + policy is active. Admins can still use the dedicated room lights when they need to override individual lamps. */ if (roomLightsLocked) { diff --git a/webui/src/controls/inputs/KeyboardInputManager.jsx b/webui/src/controls/inputs/KeyboardInputManager.jsx index 2d8486d6..6324430d 100644 --- a/webui/src/controls/inputs/KeyboardInputManager.jsx +++ b/webui/src/controls/inputs/KeyboardInputManager.jsx @@ -328,7 +328,7 @@ export default function KeyboardInputManager() { shortcuts are part of the public room-control surface. Admin sessions are allowed through when the current site mode would also allow their socket command, so keyboard behavior matches the server-side authorization and - the clickable Room Controls panel. + the clickable Room Lights panel. */ if ((ha?.lightPolicy?.locked || ha?.lightPolicy?.lockedOn) && !latest?.adminCanControlLockedLights) return; const entities = ha.entities || []; diff --git a/webui/src/help/content.js b/webui/src/help/content.js index 34cc6948..d95fa5c9 100644 --- a/webui/src/help/content.js +++ b/webui/src/help/content.js @@ -112,10 +112,10 @@ export const HELP_CONTENT = { }, { id: 'room-controls', - title: 'Room Controls', + title: 'Room Lights', items: [ - { action: 'homeAssistantOn', label: 'Next room control on' }, - { action: 'homeAssistantOff', label: 'Next room control off (reverse)' }, + { action: 'homeAssistantOn', label: 'Next room light on' }, + { action: 'homeAssistantOff', label: 'Next room light off (reverse)' }, ], }, ], @@ -163,7 +163,7 @@ export const HELP_CONTENT = { type: 'list', title: 'More controls', items: [ - 'Chat, Activities, VIP, Room Controls, Help, and Settings are below the rover controls.', + 'Chat, Activities, VIP, Room Lights, Help, and Settings are below the rover controls.', ], }, ], @@ -200,7 +200,7 @@ export const HELP_CONTENT = { type: 'list', title: 'More controls', items: [ - 'Chat, Activities, VIP, Room Controls, Help, and Settings are below the rover controls.', + 'Chat, Activities, VIP, Room Lights, Help, and Settings are below the rover controls.', ], }, ], diff --git a/webui/src/layouts/driver/MobileTabs/index.jsx b/webui/src/layouts/driver/MobileTabs/index.jsx index ee85da88..27f0b6a7 100644 --- a/webui/src/layouts/driver/MobileTabs/index.jsx +++ b/webui/src/layouts/driver/MobileTabs/index.jsx @@ -21,7 +21,7 @@ export default function MobileTabs() { Chat Activities - Room Controls + Room Lights Help Settings diff --git a/webui/src/layouts/driver/tabs/mobile/RoomControlsTab/index.jsx b/webui/src/layouts/driver/tabs/mobile/RoomControlsTab/index.jsx index ea3f0928..2cf32129 100644 --- a/webui/src/layouts/driver/tabs/mobile/RoomControlsTab/index.jsx +++ b/webui/src/layouts/driver/tabs/mobile/RoomControlsTab/index.jsx @@ -1,4 +1,4 @@ -// Mobile Room Controls Tab +// Mobile Room Lights Tab // Purpose: Owns the concrete mobile room-controls card order. import { TabPanel } from '../../../../../components/Tabs/index.jsx'; import HomeAssistantControls from '../../../../../components/HomeAssistantControls/index.jsx';