@@ -96,6 +96,10 @@ function rangeValueLabel(value, unit = "") {
9696 return `${ value } ${ unit } ` ;
9797}
9898
99+ function physicalInputSupportsTuning ( physicalInput ) {
100+ return physicalInputIsAnalog ( physicalInput ) || Boolean ( physicalInputSensitivityDescriptor ( physicalInput ) ) ;
101+ }
102+
99103function createSliderControl ( { ariaLabel, dataName, defaultValue, index, max, min, step, unit, value } ) {
100104 const input = document . createElement ( "input" ) ;
101105 input . type = "range" ;
@@ -133,7 +137,6 @@ export class AccountUserControlsPage {
133137 familyButtons : [ ...root . querySelectorAll ( "[data-account-user-controls-edit-family]" ) ] ,
134138 lists : [ ...root . querySelectorAll ( "[data-account-user-controls-list]" ) ] ,
135139 refresh : root . querySelector ( "[data-account-user-controls-refresh]" ) ,
136- saveAll : root . querySelector ( "[data-account-user-controls-save-all]" ) ,
137140 status : root . querySelector ( "[data-account-user-controls-status]" ) ,
138141 types : root . querySelector ( "[data-account-user-controls-types]" ) ,
139142 } ;
@@ -151,7 +154,6 @@ export class AccountUserControlsPage {
151154 this . setStatus ( this . deviceRefreshMessage ( ) ) ;
152155 } ) ;
153156 this . elements . addProfile ?. addEventListener ( "click" , ( ) => this . addProfileForSelectedDevice ( ) ) ;
154- this . elements . saveAll ?. addEventListener ( "click" , ( ) => this . saveCurrentState ( ) ) ;
155157 this . elements . deviceSelect ?. addEventListener ( "change" , ( ) => this . renderDeviceStatus ( ) ) ;
156158 this . elements . familyButtons . forEach ( ( button ) => {
157159 button . addEventListener ( "click" , ( ) => this . editFamilyMappings ( button . dataset . accountUserControlsEditFamily || "" ) ) ;
@@ -344,7 +346,7 @@ export class AccountUserControlsPage {
344346 row . append (
345347 tableCell ( mapping . physicalInput ) ,
346348 tableCell ( mapping . normalizedInput || mapping . positiveNormalizedInput || mapping . negativeNormalizedInput || "Unassigned" ) ,
347- tableCell ( "Visible fallback " ) ,
349+ tableCell ( "Default profile in use " ) ,
348350 ) ;
349351 rowsByFamily . get ( family ) ?. push ( row ) ;
350352 } ) ;
@@ -494,13 +496,13 @@ export class AccountUserControlsPage {
494496 }
495497
496498 inputControl ( profile , inputMapping , index ) {
497- const wrapper = document . createElement ( "div" ) ;
498- wrapper . className = "content-grid" ;
499- wrapper . dataset . accountUserControlsInputPair = "true" ;
499+ const row = document . createElement ( "tr" ) ;
500+ row . dataset . accountUserControlsInputPair = "true" ;
500501 const editablePhysicalInput = profile . deviceType === "Keyboard" || profile . deviceType === "Mouse" ;
501502 const physicalInputControl = editablePhysicalInput
502503 ? document . createElement ( "input" )
503504 : document . createElement ( "strong" ) ;
505+ const physicalInputCell = document . createElement ( "td" ) ;
504506 if ( editablePhysicalInput ) {
505507 physicalInputControl . type = "text" ;
506508 physicalInputControl . value = inputMapping . physicalInput ;
@@ -509,6 +511,7 @@ export class AccountUserControlsPage {
509511 } else {
510512 physicalInputControl . textContent = inputMapping . physicalInput ;
511513 }
514+ physicalInputCell . append ( physicalInputControl ) ;
512515 const stack = document . createElement ( "div" ) ;
513516 stack . className = "content-stack content-stack--compact" ;
514517 const normalizedOptions = [
@@ -538,26 +541,43 @@ export class AccountUserControlsPage {
538541 select . dataset . accountUserControlsInputNormalized = String ( index ) ;
539542 stack . append ( select ) ;
540543 }
541- if ( physicalInputIsAnalog ( inputMapping . physicalInput ) || normalizedInputIsAnalog ( inputMapping . normalizedInput ) ) {
544+ const validation = document . createElement ( "p" ) ;
545+ validation . className = "status" ;
546+ validation . dataset . accountUserControlsInputValidation = String ( index ) ;
547+ stack . append ( validation ) ;
548+
549+ const deadzoneCell = document . createElement ( "td" ) ;
550+ if ( physicalInputSupportsTuning ( inputMapping . physicalInput ) ) {
542551 const deadzone = document . createElement ( "input" ) ;
543552 deadzone . type = "number" ;
544553 deadzone . min = "0" ;
545554 deadzone . max = "1" ;
546555 deadzone . step = "0.05" ;
547556 deadzone . value = String ( inputMapping . deadzone ) ;
548557 deadzone . dataset . accountUserControlsDeadzone = String ( index ) ;
558+ deadzoneCell . append ( deadzone ) ;
559+ } else {
560+ deadzoneCell . textContent = "Not applicable" ;
561+ }
562+
563+ const invertCell = document . createElement ( "td" ) ;
564+ if ( physicalInputSupportsTuning ( inputMapping . physicalInput ) ) {
549565 const invert = document . createElement ( "input" ) ;
550566 invert . type = "checkbox" ;
551567 invert . checked = Boolean ( inputMapping . invert ) ;
552568 invert . dataset . accountUserControlsInvert = String ( index ) ;
553- stack . append ( labeledControl ( "Deadzone" , deadzone ) , labeledControl ( "Invert" , invert ) ) ;
569+ invertCell . append ( invert ) ;
570+ } else {
571+ invertCell . textContent = "Not applicable" ;
554572 }
573+
574+ const sensitivityCell = document . createElement ( "td" ) ;
555575 const sensitivity = physicalInputSensitivityDescriptor ( inputMapping . physicalInput ) ;
556576 if ( sensitivity ) {
557577 const value = Number . isFinite ( Number ( inputMapping . sensitivity ) )
558578 ? Number ( inputMapping . sensitivity )
559579 : sensitivity . defaultValue ;
560- const slider = createSliderControl ( {
580+ sensitivityCell . append ( createSliderControl ( {
561581 ariaLabel : sensitivity . label ,
562582 dataName : "accountUserControlsSensitivity" ,
563583 defaultValue : sensitivity . defaultValue ,
@@ -567,21 +587,32 @@ export class AccountUserControlsPage {
567587 step : sensitivity . step ,
568588 unit : sensitivity . unit ,
569589 value,
570- } ) ;
571- stack . append ( labeledControl ( sensitivity . label , slider ) ) ;
590+ } ) ) ;
591+ } else {
592+ sensitivityCell . textContent = "Not applicable" ;
572593 }
573- const validation = document . createElement ( "p" ) ;
574- validation . className = "status" ;
575- validation . dataset . accountUserControlsInputValidation = String ( index ) ;
576- stack . append ( validation ) ;
577- wrapper . append ( physicalInputControl , stack ) ;
578- return wrapper ;
594+
595+ row . append ( physicalInputCell , controlCell ( stack ) , deadzoneCell , invertCell , sensitivityCell ) ;
596+ return row ;
579597 }
580598
581599 renderEditingRows ( values = { } ) {
582600 const profile = this . normalizeProfile ( values ) ;
583601 const row = document . createElement ( "tr" ) ;
584602 row . dataset . accountUserControlsEditingRow = "true" ;
603+ const controllerName = document . createElement ( "input" ) ;
604+ controllerName . type = "text" ;
605+ controllerName . value = profile . controllerName ;
606+ controllerName . dataset . accountUserControlsControllerName = "true" ;
607+ controllerName . setAttribute ( "aria-label" , "Physical Controller name" ) ;
608+ const controllerCell = document . createElement ( "td" ) ;
609+ const controllerStack = document . createElement ( "div" ) ;
610+ controllerStack . className = "content-stack content-stack--compact" ;
611+ const deviceType = document . createElement ( "span" ) ;
612+ deviceType . className = "status" ;
613+ deviceType . textContent = profile . deviceType ;
614+ controllerStack . append ( deviceType , labeledControl ( "Physical Controller" , controllerName ) ) ;
615+ controllerCell . append ( controllerStack ) ;
585616 const actions = document . createElement ( "td" ) ;
586617 const group = document . createElement ( "div" ) ;
587618 group . className = "action-group action-group--tight" ;
@@ -591,7 +622,7 @@ export class AccountUserControlsPage {
591622 ) ;
592623 actions . append ( group ) ;
593624 row . append (
594- tableCell ( ` ${ profile . deviceType } : ${ profile . controllerName } ` ) ,
625+ controllerCell ,
595626 tableCell ( `${ profile . inputMappings . length } Physical Inputs` ) ,
596627 tableCell ( this . profileInputSummary ( profile ) ) ,
597628 tableCell ( this . profileAnalogSummary ( profile ) ) ,
@@ -604,10 +635,25 @@ export class AccountUserControlsPage {
604635 detailsRow . dataset . accountUserControlsEditingDetails = "true" ;
605636 const detailsCell = document . createElement ( "td" ) ;
606637 detailsCell . colSpan = 7 ;
607- const grid = document . createElement ( "div" ) ;
608- grid . className = "content-grid content-grid--three" ;
609- grid . append ( ...profile . inputMappings . map ( ( inputMapping , index ) => this . inputControl ( profile , inputMapping , index ) ) ) ;
610- detailsCell . append ( grid ) ;
638+ const wrapper = document . createElement ( "div" ) ;
639+ wrapper . className = "table-wrapper" ;
640+ const table = document . createElement ( "table" ) ;
641+ table . className = "data-table" ;
642+ table . dataset . accountUserControlsGeneratedInputTable = "true" ;
643+ table . setAttribute ( "aria-label" , `${ profile . controllerName } generated controller inputs` ) ;
644+ const head = document . createElement ( "thead" ) ;
645+ const headRow = document . createElement ( "tr" ) ;
646+ [ "Physical Input" , "Normalized Control" , "Deadzone" , "Invert" , "Sensitivity" ] . forEach ( ( heading ) => {
647+ const cell = document . createElement ( "th" ) ;
648+ cell . textContent = heading ;
649+ headRow . append ( cell ) ;
650+ } ) ;
651+ head . append ( headRow ) ;
652+ const body = document . createElement ( "tbody" ) ;
653+ body . append ( ...profile . inputMappings . map ( ( inputMapping , index ) => this . inputControl ( profile , inputMapping , index ) ) ) ;
654+ table . append ( head , body ) ;
655+ wrapper . append ( table ) ;
656+ detailsCell . append ( wrapper ) ;
611657 detailsRow . append ( detailsCell ) ;
612658 return [ row , detailsRow ] ;
613659 }
@@ -650,6 +696,16 @@ export class AccountUserControlsPage {
650696 profileFromEditingRow ( ) {
651697 const values = this . editingProfile ?. values || { } ;
652698 const details = this . root . querySelector ( "[data-account-user-controls-editing-details]" ) ;
699+ const controllerNameInput = this . root . querySelector ( "[data-account-user-controls-controller-name]" ) ;
700+ const previousControllerName = normalizeText ( values . controllerName ) ;
701+ const controllerName = normalizeText ( controllerNameInput ?. value ?? previousControllerName )
702+ || previousControllerName
703+ || normalizeText ( values . deviceType )
704+ || "Game Controller" ;
705+ const previousProfileName = normalizeText ( values . mappingProfile || values . profileName ) ;
706+ const mappingProfile = previousProfileName === `${ previousControllerName } Profile`
707+ ? `${ controllerName } Profile`
708+ : previousProfileName || `${ controllerName } Profile` ;
653709 const inputMappings = ( values . inputMappings || [ ] ) . map ( ( mapping , index ) => {
654710 const physicalInputControl = details ?. querySelector ( `[data-account-user-controls-physical-input="${ index } "]` ) ;
655711 const normalizedSelect = details ?. querySelector ( `[data-account-user-controls-input-normalized="${ index } "]` ) ;
@@ -673,9 +729,11 @@ export class AccountUserControlsPage {
673729 } ) ;
674730 return this . normalizeProfile ( {
675731 ...values ,
732+ controllerName,
676733 id : this . editingProfile ?. id || "" ,
677734 inputMappings,
678735 inputs : inputMappings . map ( ( mapping ) => mapping . physicalInput ) ,
736+ mappingProfile,
679737 } ) ;
680738 }
681739
@@ -761,23 +819,6 @@ export class AccountUserControlsPage {
761819 this . setStatus ( `PASS: Saved ${ profile . mappingProfile } .` ) ;
762820 }
763821
764- saveCurrentState ( ) {
765- if ( this . editingProfile ) {
766- this . saveEditingProfile ( ) ;
767- return ;
768- }
769- if ( ! this . profiles . length ) {
770- this . setStatus ( "FAIL: Create a user control profile before saving." ) ;
771- return ;
772- }
773- if ( ! this . saveProfiles ( this . profiles ) ) {
774- this . setStatus ( "FAIL: Account user controls could not reach the shared DB adapter." ) ;
775- return ;
776- }
777- this . renderProfiles ( ) ;
778- this . setStatus ( "PASS: Saved account user controls." ) ;
779- }
780-
781822 handleListClick ( event ) {
782823 const target = event . target instanceof Element ? event . target . closest ( "button" ) : null ;
783824 if ( ! target ) {
0 commit comments