@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
206 lines • 15.1 kB
JavaScript
import*as i18n from"../../../../core/i18n/i18n.js";import*as Buttons from"../../../../ui/components/buttons/buttons.js";import*as ComponentHelpers from"../../../../ui/components/helpers/helpers.js";import*as LitHtml from"../../../../ui/lit-html/lit-html.js";import userAgentClientHintsFormStyles from"./userAgentClientHintsForm.css.js";import*as Input from"../../../../ui/components/input/input.js";import*as IconButton from"../../../../ui/components/icon_button/icon_button.js";import*as EmulationUtils from"../utils/utils.js";const UIStrings={title:"User agent client hints",useragent:"User agent (Sec-CH-UA)",fullVersionList:"Full version list (Sec-CH-UA-Full-Version-List)",brandProperties:"User agent properties",brandName:"Brand",brandNameAriaLabel:"Brand {PH1}",significantBrandVersionPlaceholder:"Significant version (e.g. 87)",brandVersionPlaceholder:"Version (e.g. 87.0.4280.88)",brandVersionAriaLabel:"Version {PH1}",addBrand:"Add Brand",brandUserAgentDelete:"Delete brand from user agent section",brandFullVersionListDelete:"Delete brand from full version list",fullBrowserVersion:"Full browser version (Sec-CH-UA-Full-Browser-Version)",fullBrowserVersionPlaceholder:"Full browser version (e.g. 87.0.4280.88)",platformLabel:"Platform (Sec-CH-UA-Platform / Sec-CH-UA-Platform-Version)",platformProperties:"Platform properties",platformVersion:"Platform version",platformPlaceholder:"Platform (e.g. Android)",architecture:"Architecture (Sec-CH-UA-Arch)",architecturePlaceholder:"Architecture (e.g. x86)",deviceProperties:"Device properties",deviceModel:"Device model (Sec-CH-UA-Model)",mobileCheckboxLabel:"Mobile",update:"Update",notRepresentable:"Not representable as structured headers string.",userAgentClientHintsInfo:"User agent client hints are an alternative to the user agent string that identify the browser and the device in a more structured way with better privacy accounting.",addedBrand:"Added brand row",deletedBrand:"Deleted brand row",learnMore:"Learn more"},str_=i18n.i18n.registerUIStrings("panels/settings/emulation/components/UserAgentClientHintsForm.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class ClientHintsChangeEvent extends Event{static eventName="clienthintschange";constructor(){super(ClientHintsChangeEvent.eventName)}}export class ClientHintsSubmitEvent extends Event{static eventName="clienthintssubmit";detail;constructor(e){super(ClientHintsSubmitEvent.eventName),this.detail={value:e}}}const DEFAULT_METADATA={brands:[{brand:"",version:""}],fullVersionList:[{brand:"",version:""}],fullVersion:"",platform:"",platformVersion:"",architecture:"",model:"",mobile:!1};export class UserAgentClientHintsForm extends HTMLElement{static litTagName=LitHtml.literal`devtools-user-agent-client-hints-form`;#e=this.attachShadow({mode:"open"});#t=!1;#n=!1;#i=DEFAULT_METADATA;#r=!1;#a=!1;#s="";connectedCallback(){this.#e.adoptedStyleSheets=[Input.checkboxStyles,userAgentClientHintsFormStyles]}set value(e){const{metaData:t=DEFAULT_METADATA,showMobileCheckbox:n=!1,showSubmitButton:i=!1}=e;this.#i={...this.#i,...t},this.#r=n,this.#a=i,this.#l()}get value(){return{metaData:this.#i}}set disabled(e){this.#n=e,this.#t=!1,this.#l()}get disabled(){return this.#n}#o=e=>{"Space"!==e.code&&"Enter"!==e.code&&"ArrowLeft"!==e.code&&"ArrowRight"!==e.code||(e.stopPropagation(),this.#d(e.code))};#d=e=>{this.#n||"ArrowLeft"===e&&!this.#t||"ArrowRight"===e&&this.#t||(this.#t=!this.#t,this.#l())};#c=(e,t,n)=>{const i=this.#i.brands?.map(((i,r)=>{if(r===t){const{brand:t,version:r}=i;return"brandName"===n?{brand:e,version:r}:{brand:t,version:e}}return i}));this.#i={...this.#i,brands:i},this.dispatchEvent(new ClientHintsChangeEvent),this.#l()};#h=(e,t,n)=>{const i=this.#i.fullVersionList?.map(((i,r)=>{if(r===t){const{brand:t,version:r}=i;return"brandName"===n?{brand:e,version:r}:{brand:t,version:e}}return i}));this.#i={...this.#i,fullVersionList:i},this.dispatchEvent(new ClientHintsChangeEvent),this.#l()};#u=e=>{const{brands:t=[]}=this.#i;t.splice(e,1),this.#i={...this.#i,brands:t},this.dispatchEvent(new ClientHintsChangeEvent),this.#s=i18nString(UIStrings.deletedBrand),this.#l();let n=this.shadowRoot?.getElementById(`ua-brand-${e+1}-input`);n||(n=this.shadowRoot?.getElementById("add-brand-button")),n?.focus()};#g=e=>{const{fullVersionList:t=[]}=this.#i;t.splice(e,1),this.#i={...this.#i,fullVersionList:t},this.dispatchEvent(new ClientHintsChangeEvent),this.#s=i18nString(UIStrings.deletedBrand),this.#l();let n=this.shadowRoot?.getElementById(`fvl-brand-${e+1}-input`);n||(n=this.shadowRoot?.getElementById("add-fvl-brand-button")),n?.focus()};#m=()=>{const{brands:e}=this.#i;this.#i={...this.#i,brands:[...Array.isArray(e)?e:[],{brand:"",version:""}]},this.dispatchEvent(new ClientHintsChangeEvent),this.#s=i18nString(UIStrings.addedBrand),this.#l();const t=this.shadowRoot?.querySelectorAll(".ua-brand-name-input");if(t){const e=Array.from(t).pop();e&&e.focus()}};#p=e=>{"Space"!==e.code&&"Enter"!==e.code||(e.preventDefault(),this.#m())};#b=()=>{const{fullVersionList:e}=this.#i;this.#i={...this.#i,fullVersionList:[...Array.isArray(e)?e:[],{brand:"",version:""}]},this.dispatchEvent(new ClientHintsChangeEvent),this.#s=i18nString(UIStrings.addedBrand),this.#l();const t=this.shadowRoot?.querySelectorAll(".fvl-brand-name-input");if(t){const e=Array.from(t).pop();e&&e.focus()}};#S=e=>{"Space"!==e.code&&"Enter"!==e.code||(e.preventDefault(),this.#b())};#f=(e,t)=>{e in this.#i&&(this.#i={...this.#i,[e]:t},this.#l()),this.dispatchEvent(new ClientHintsChangeEvent)};#v=e=>{"Space"!==e.code&&"Enter"!==e.code||(e.preventDefault(),e.target.click())};#I=e=>{e.preventDefault(),this.#a&&(this.dispatchEvent(new ClientHintsSubmitEvent(this.#i)),this.#l())};#$(e,t,n,i){return LitHtml.html`
<label class="full-row label input-field-label-container">
${e}
<input
class="input-field"
type="text"
=${e=>{const t=e.target.value;this.#f(i,t)}}
.value=${n}
placeholder=${t}
/>
</label>
`}#U(){const{platform:e,platformVersion:t}=this.#i;return LitHtml.html`
<span class="full-row label">${i18nString(UIStrings.platformLabel)}</span>
<div class="full-row brand-row" aria-label=${i18nString(UIStrings.platformProperties)} role="group">
<input
class="input-field half-row"
type="text"
=${e=>{const t=e.target.value;this.#f("platform",t)}}
.value=${e}
placeholder=${i18nString(UIStrings.platformPlaceholder)}
aria-label=${i18nString(UIStrings.platformLabel)}
/>
<input
class="input-field half-row"
type="text"
=${e=>{const t=e.target.value;this.#f("platformVersion",t)}}
.value=${t}
placeholder=${i18nString(UIStrings.platformVersion)}
aria-label=${i18nString(UIStrings.platformVersion)}
/>
</div>
`}#A(){const{model:e,mobile:t}=this.#i,n=this.#r?LitHtml.html`
<label class="mobile-checkbox-container">
<input type="checkbox" =${e=>{const t=e.target.checked;this.#f("mobile",t)}} .checked=${t} />
${i18nString(UIStrings.mobileCheckboxLabel)}
</label>
`:LitHtml.html``;return LitHtml.html`
<span class="full-row label">${i18nString(UIStrings.deviceModel)}</span>
<div class="full-row brand-row" aria-label=${i18nString(UIStrings.deviceProperties)} role="group">
<input
class="input-field ${this.#r?"device-model-input":"full-row"}"
type="text"
=${e=>{const t=e.target.value;this.#f("model",t)}}
.value=${e}
placeholder=${i18nString(UIStrings.deviceModel)}
/>
${n}
</div>
`}#w(){const{brands:e=[{brand:"",version:""}]}=this.#i,t=e.map(((e,t)=>{const{brand:n,version:i}=e,r=()=>{this.#u(t)};return LitHtml.html`
<div class="full-row brand-row" aria-label=${i18nString(UIStrings.brandProperties)} role="group">
<input
class="input-field ua-brand-name-input"
type="text"
=${e=>{const n=e.target.value;this.#c(n,t,"brandName")}}
.value=${n}
id="ua-brand-${t+1}-input"
placeholder=${i18nString(UIStrings.brandName)}
aria-label=${i18nString(UIStrings.brandNameAriaLabel,{PH1:t+1})}
/>
<input
class="input-field"
type="text"
=${e=>{const n=e.target.value;this.#c(n,t,"brandVersion")}}
.value=${i}
placeholder=${i18nString(UIStrings.significantBrandVersionPlaceholder)}
aria-label=${i18nString(UIStrings.brandVersionAriaLabel,{PH1:t+1})}
/>
<${IconButton.Icon.Icon.litTagName}
.data=${{color:"var(--icon-default)",iconName:"bin",width:"16px",height:"16px"}}
title=${i18nString(UIStrings.brandUserAgentDelete)}
class="delete-icon"
tabindex="0"
role="button"
=${r}
=${e=>{"Space"!==e.code&&"Enter"!==e.code||(e.preventDefault(),r())}}
aria-label=${i18nString(UIStrings.brandUserAgentDelete)}
>
</${IconButton.Icon.Icon.litTagName}>
</div>
`}));return LitHtml.html`
<span class="full-row label">${i18nString(UIStrings.useragent)}</span>
${t}
<div
class="add-container full-row"
role="button"
tabindex="0"
id="add-brand-button"
aria-label=${i18nString(UIStrings.addBrand)}
=${this.#m}
=${this.#p}
>
<${IconButton.Icon.Icon.litTagName}
aria-hidden="true"
.data=${{color:"var(--icon-default)",iconName:"plus",width:"16px"}}
>
</${IconButton.Icon.Icon.litTagName}>
${i18nString(UIStrings.addBrand)}
</div>
`}#C(){const{fullVersionList:e=[{brand:"",version:""}]}=this.#i,t=e.map(((e,t)=>{const{brand:n,version:i}=e,r=()=>{this.#g(t)};return LitHtml.html`
<div class="full-row brand-row" aria-label=${i18nString(UIStrings.brandProperties)} role="group">
<input
class="input-field fvl-brand-name-input"
type="text"
=${e=>{const n=e.target.value;this.#h(n,t,"brandName")}}
.value=${n}
id="fvl-brand-${t+1}-input"
placeholder=${i18nString(UIStrings.brandName)}
aria-label=${i18nString(UIStrings.brandNameAriaLabel,{PH1:t+1})}
/>
<input
class="input-field"
type="text"
=${e=>{const n=e.target.value;this.#h(n,t,"brandVersion")}}
.value=${i}
placeholder=${i18nString(UIStrings.brandVersionPlaceholder)}
aria-label=${i18nString(UIStrings.brandVersionAriaLabel,{PH1:t+1})}
/>
<${IconButton.Icon.Icon.litTagName}
.data=${{color:"var(--icon-default)",iconName:"bin",width:"16px",height:"16px"}}
title=${i18nString(UIStrings.brandFullVersionListDelete)}
class="delete-icon"
tabindex="0"
role="button"
=${r}
=${e=>{"Space"!==e.code&&"Enter"!==e.code||(e.preventDefault(),r())}}
aria-label=${i18nString(UIStrings.brandFullVersionListDelete)}
>
</${IconButton.Icon.Icon.litTagName}>
</div>
`}));return LitHtml.html`
<span class="full-row label">${i18nString(UIStrings.fullVersionList)}</span>
${t}
<div
class="add-container full-row"
role="button"
tabindex="0"
id="add-fvl-brand-button"
aria-label=${i18nString(UIStrings.addBrand)}
=${this.#b}
=${this.#S}
>
<${IconButton.Icon.Icon.litTagName}
aria-hidden="true"
.data=${{color:"var(--icon-default)",iconName:"plus",width:"16px"}}
>
</${IconButton.Icon.Icon.litTagName}>
${i18nString(UIStrings.addBrand)}
</div>
`}#l(){const{fullVersion:e,architecture:t}=this.#i,n=this.#w(),i=this.#C(),r=this.#$(i18nString(UIStrings.fullBrowserVersion),i18nString(UIStrings.fullBrowserVersionPlaceholder),e||"","fullVersion"),a=this.#U(),s=this.#$(i18nString(UIStrings.architecture),i18nString(UIStrings.architecturePlaceholder),t,"architecture"),l=this.#A(),o=this.#a?LitHtml.html`
<${Buttons.Button.Button.litTagName}
.variant=${"secondary"}
.type=${"submit"}
>
${i18nString(UIStrings.update)}
</${Buttons.Button.Button.litTagName}>
`:LitHtml.nothing,d=LitHtml.html`
<section class="root">
<div
class="tree-title"
role="button"
=${this.#d}
tabindex="0"
=${this.#o}
aria-expanded=${this.#t}
aria-controls="form-container"
=${this.#n}
aria-disabled=${this.#n}
aria-label=${i18nString(UIStrings.title)}
>
<${IconButton.Icon.Icon.litTagName}
class=${this.#t?"rotate-icon":""}
.data=${{color:"var(--icon-default)",iconName:"triangle-right",width:"14px"}}
></${IconButton.Icon.Icon.litTagName}>
${i18nString(UIStrings.title)}
<${IconButton.Icon.Icon.litTagName}
.data=${{color:"var(--icon-default)",iconName:"info",width:"16px"}}
title=${i18nString(UIStrings.userAgentClientHintsInfo)}
class='info-icon',
></${IconButton.Icon.Icon.litTagName}>
<x-link
tabindex="0"
href="https://web.dev/user-agent-client-hints/"
target="_blank"
class="link"
=${this.#v}
aria-label=${i18nString(UIStrings.userAgentClientHintsInfo)}
>
${i18nString(UIStrings.learnMore)}
</x-link>
</div>
<form
id="form-container"
class="form-container ${this.#t?"":"hide-container"}"
=${this.#I}
>
${n}
${i}
${r}
${a}
${s}
${l}
${o}
</form>
<div aria-live="polite" aria-label=${this.#s}></div>
</section>
`;LitHtml.render(d,this.#e,{host:this})}validate=()=>{for(const[e,t]of Object.entries(this.#i))if("brands"===e||"fullVersionList"===e){const e=this.#i.brands?.every((({brand:e,version:t})=>{const n=EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(e,i18nString(UIStrings.notRepresentable)),i=EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(t,i18nString(UIStrings.notRepresentable));return n.valid&&i.valid}));if(!e)return{valid:!1,errorMessage:i18nString(UIStrings.notRepresentable)}}else{const e=EmulationUtils.UserAgentMetadata.validateAsStructuredHeadersString(t,i18nString(UIStrings.notRepresentable));if(!e.valid)return e}return{valid:!0}}}ComponentHelpers.CustomElements.defineComponent("devtools-user-agent-client-hints-form",UserAgentClientHintsForm);