@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 25.6 kB
JavaScript
import*as Common from"../../core/common/common.js";import*as Host from"../../core/host/host.js";import*as i18n from"../../core/i18n/i18n.js";import appManifestViewStyles from"./appManifestView.css.js";import*as SDK from"../../core/sdk/sdk.js";import*as InlineEditor from"../../ui/legacy/components/inline_editor/inline_editor.js";import*as Components from"../../ui/legacy/components/utils/utils.js";import*as UI from"../../ui/legacy/legacy.js";import*as IconButton from"../../ui/components/icon_button/icon_button.js";import*as ApplicationComponents from"./components/components.js";const UIStrings={errorsAndWarnings:"Errors and warnings",installability:"Installability",identity:"Identity",presentation:"Presentation",protocolHandlers:"Protocol Handlers",icons:"Icons",windowControlsOverlay:"Window Controls Overlay",name:"Name",shortName:"Short name",computedAppId:"Computed App Id",appIdExplainer:"This is used by the browser to know whether the manifest should be updating an existing application, or whether it refers to a new web app that can be installed.",learnMore:"Learn more",appIdNote:"{PH1} {PH2} is not specified in the manifest, {PH3} is used instead. To specify an App Id that matches the current identity, set the {PH4} field to {PH5} {PH6}.",note:"Note:",copyToClipboard:"Copy to clipboard",copiedToClipboard:"Copied suggested ID {PH1} to clipboard",description:"Description",startUrl:"Start URL",themeColor:"Theme color",backgroundColor:"Background color",darkThemeColor:"Dark theme color",darkBackgroundColor:"Dark background color",orientation:"Orientation",display:"Display",newNoteUrl:"New note URL",descriptionMayBeTruncated:"Description may be truncated.",showOnlyTheMinimumSafeAreaFor:"Show only the minimum safe area for maskable icons",documentationOnMaskableIcons:"documentation on maskable icons",needHelpReadOurS:"Need help? Read {PH1}.",shortcutS:"Shortcut #{PH1}",shortcutSShouldIncludeAXPixel:"Shortcut #{PH1} should include a 96x96 pixel icon",screenshotS:"Screenshot #{PH1}",pageIsNotLoadedInTheMainFrame:"Page is not loaded in the main frame",pageIsNotServedFromASecureOrigin:"Page is not served from a secure origin",pageHasNoManifestLinkUrl:"Page has no manifest <link> `URL`",manifestCouldNotBeFetchedIsEmpty:"Manifest could not be fetched, is empty, or could not be parsed",manifestStartUrlIsNotValid:"Manifest '`start_URL`' is not valid",manifestDoesNotContainANameOr:"Manifest does not contain a '`name`' or '`short_name`' field",manifestDisplayPropertyMustBeOne:"Manifest '`display`' property must be one of '`standalone`', '`fullscreen`', or '`minimal-ui`'",manifestDoesNotContainASuitable:"Manifest does not contain a suitable icon - PNG, SVG or WebP format of at least {PH1}px is required, the '`sizes`' attribute must be set, and the '`purpose`' attribute, if set, must include '`any`'.",avoidPurposeAnyAndMaskable:"Declaring an icon with '`purpose: \"any maskable\"`' is discouraged. It is likely to look incorrect on some platforms due to too much or too little padding.",noSuppliedIconIsAtLeastSpxSquare:"No supplied icon is at least {PH1} pixels square in `PNG`, `SVG` or `WebP` format, with the purpose attribute unset or set to '`any`'.",couldNotDownloadARequiredIcon:"Could not download a required icon from the manifest",downloadedIconWasEmptyOr:"Downloaded icon was empty or corrupted",theSpecifiedApplicationPlatform:"The specified application platform is not supported on `Android`",noPlayStoreIdProvided:"No Play store ID provided",thePlayStoreAppUrlAndPlayStoreId:"The Play Store app URL and Play Store ID do not match",theAppIsAlreadyInstalled:"The app is already installed",aUrlInTheManifestContainsA:"A URL in the manifest contains a username, password, or port",pageIsLoadedInAnIncognitoWindow:"Page is loaded in an incognito window",pageDoesNotWorkOffline:"Page does not work offline",couldNotCheckServiceWorker:"Could not check `service worker` without a '`start_url`' field in the manifest",manifestSpecifies:"Manifest specifies '`prefer_related_applications`: true'",preferrelatedapplicationsIsOnly:"'`prefer_related_applications`' is only supported on `Chrome` Beta and Stable channels on `Android`.",manifestContainsDisplayoverride:"Manifest contains '`display_override`' field, and the first supported display mode must be one of '`standalone`', '`fullscreen`', or '`minimal-ui`'",pageDoesNotWorkOfflineThePage:"Page does not work offline. Starting in Chrome 93, the installability criteria are changing, and this site will not be installable. See {PH1} for more information.",imageFromS:"Image from {PH1}",screenshot:"Screenshot",icon:"Icon",sSrcIsNotSet:"{PH1} '`src`' is not set",sUrlSFailedToParse:"{PH1} URL ''{PH2}'' failed to parse",sSFailedToLoad:"{PH1} {PH2} failed to load",sSDoesNotSpecifyItsSizeInThe:"{PH1} {PH2} does not specify its size in the manifest",sSShouldSpecifyItsSizeAs:"{PH1} {PH2} should specify its size as `[width]x[height]`",sSShouldHaveSquareIcon:"Most operating systems require square icons. Please include at least one square icon in the array.",actualSizeSspxOfSSDoesNotMatch:"Actual size ({PH1}×{PH2})px of {PH3} {PH4} does not match specified size ({PH5}×{PH6}px)",actualWidthSpxOfSSDoesNotMatch:"Actual width ({PH1}px) of {PH2} {PH3} does not match specified width ({PH4}px)",actualHeightSpxOfSSDoesNotMatch:"Actual height ({PH1}px) of {PH2} {PH3} does not match specified height ({PH4}px)",sSSizeShouldBeAtLeast320:"{PH1} {PH2} size should be at least 320×320",sSSizeShouldBeAtMost3840:"{PH1} {PH2} size should be at most 3840×3840",sSWidthDoesNotComplyWithRatioRequirement:"{PH1} {PH2} width can't be more than 2.3 times as long as the height",sSHeightDoesNotComplyWithRatioRequirement:"{PH1} {PH2} height can't be more than 2.3 times as long as the width",screenshotPixelSize:'Screenshot {url} should specify a pixel size `[width]x[height]` instead of `"any"` as first size.',displayOverride:"display-override",wcoFound:"Chrome has successfully found the {PH1} value for the {PH2} field in the {PH3}.",wcoNotFound:"Define {PH1} in the manifest to use the Window Controls Overlay API and customize your app's title bar.",customizePwaTitleBar:"Customize the window controls overlay of your PWA's title bar.",wcoNeedHelpReadMore:"Need help? Read {PH1}."},str_=i18n.i18n.registerUIStrings("panels/application/AppManifestView.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class AppManifestView extends UI.Widget.VBox{emptyView;reportView;errorsSection;installabilitySection;identitySection;presentationSection;iconsSection;windowsControlsOverlaySection;protocolHandlersSection;shortcutSections;screenshotsSections;nameField;shortNameField;descriptionField;startURLField;themeColorSwatch;backgroundColorSwatch;darkThemeColorField;darkThemeColorSwatch;darkBackgroundColorField;darkBackgroundColorSwatch;orientationField;displayField;newNoteUrlField;throttler;registeredListeners;target;resourceTreeModel;serviceWorkerManager;protocolHandlersView;manifestLink;constructor(e,t,i){super(!0),this.contentElement.classList.add("manifest-container"),Common.Settings.Settings.instance().moduleSetting("colorFormat").addChangeListener(this.updateManifest.bind(this,!0)),this.emptyView=e,this.emptyView.appendLink("https://web.dev/add-manifest/"),this.emptyView.show(this.contentElement),this.emptyView.hideWidget(),this.reportView=t,this.reportView.element.classList.add("manifest-view-header"),this.reportView.show(this.contentElement),this.reportView.hideWidget(),this.errorsSection=this.reportView.appendSection(i18nString(UIStrings.errorsAndWarnings)),this.installabilitySection=this.reportView.appendSection(i18nString(UIStrings.installability)),this.identitySection=this.reportView.appendSection(i18nString(UIStrings.identity)),this.presentationSection=this.reportView.appendSection(i18nString(UIStrings.presentation)),this.protocolHandlersSection=this.reportView.appendSection(i18nString(UIStrings.protocolHandlers)),this.protocolHandlersView=new ApplicationComponents.ProtocolHandlersView.ProtocolHandlersView,this.protocolHandlersSection.appendFieldWithCustomView(this.protocolHandlersView),this.iconsSection=this.reportView.appendSection(i18nString(UIStrings.icons),"report-section-icons"),this.windowsControlsOverlaySection=this.reportView.appendSection(UIStrings.windowControlsOverlay),this.shortcutSections=[],this.screenshotsSections=[],this.nameField=this.identitySection.appendField(i18nString(UIStrings.name)),this.shortNameField=this.identitySection.appendField(i18nString(UIStrings.shortName)),this.descriptionField=this.identitySection.appendFlexedField(i18nString(UIStrings.description)),this.startURLField=this.presentationSection.appendField(i18nString(UIStrings.startUrl)),UI.ARIAUtils.setLabel(this.startURLField,i18nString(UIStrings.startUrl));const n=this.presentationSection.appendField(i18nString(UIStrings.themeColor));this.themeColorSwatch=new InlineEditor.ColorSwatch.ColorSwatch,n.appendChild(this.themeColorSwatch);const o=this.presentationSection.appendField(i18nString(UIStrings.backgroundColor));this.backgroundColorSwatch=new InlineEditor.ColorSwatch.ColorSwatch,o.appendChild(this.backgroundColorSwatch),this.darkThemeColorField=this.presentationSection.appendField(i18nString(UIStrings.darkThemeColor)),this.darkThemeColorSwatch=new InlineEditor.ColorSwatch.ColorSwatch,this.darkThemeColorField.appendChild(this.darkThemeColorSwatch),this.darkBackgroundColorField=this.presentationSection.appendField(i18nString(UIStrings.darkBackgroundColor)),this.darkBackgroundColorSwatch=new InlineEditor.ColorSwatch.ColorSwatch,this.darkBackgroundColorField.appendChild(this.darkBackgroundColorSwatch),this.orientationField=this.presentationSection.appendField(i18nString(UIStrings.orientation)),this.displayField=this.presentationSection.appendField(i18nString(UIStrings.display)),this.newNoteUrlField=this.presentationSection.appendField(i18nString(UIStrings.newNoteUrl)),this.throttler=i,SDK.TargetManager.TargetManager.instance().observeTargets(this),this.registeredListeners=[]}getStaticSections(){return[this.identitySection,this.presentationSection,this.protocolHandlersSection,this.iconsSection,this.windowsControlsOverlaySection]}getManifestElement(){return this.reportView.getHeaderElement()}targetAdded(e){e===SDK.TargetManager.TargetManager.instance().primaryPageTarget()&&(this.target=e,this.resourceTreeModel=e.model(SDK.ResourceTreeModel.ResourceTreeModel),this.serviceWorkerManager=e.model(SDK.ServiceWorkerManager.ServiceWorkerManager),this.resourceTreeModel&&this.serviceWorkerManager&&(this.updateManifest(!0),this.registeredListeners=[this.resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.DOMContentLoaded,(()=>{this.updateManifest(!0)})),this.serviceWorkerManager.addEventListener(SDK.ServiceWorkerManager.Events.RegistrationUpdated,(()=>{this.updateManifest(!1)}))]))}targetRemoved(e){this.target===e&&this.resourceTreeModel&&this.serviceWorkerManager&&(delete this.resourceTreeModel,delete this.serviceWorkerManager,Common.EventTarget.removeEventListeners(this.registeredListeners))}async updateManifest(e){if(!this.resourceTreeModel)return;const[{url:t,data:i,errors:n},o,r]=await Promise.all([this.resourceTreeModel.fetchAppManifest(),this.resourceTreeModel.getInstallabilityErrors(),this.resourceTreeModel.getAppId()]);this.throttler.schedule((()=>this.renderManifest(t,i,n,o,r)),e)}async renderManifest(e,t,i,n,o){const r=o?.appId||null,s=o?.recommendedId||null;if(!t&&!i.length)return this.emptyView.showWidget(),this.reportView.hideWidget(),void this.contentElement.dispatchEvent(new CustomEvent("manifestDetection",{detail:!1}));this.emptyView.hideWidget(),this.reportView.showWidget(),this.contentElement.dispatchEvent(new CustomEvent("manifestDetection",{detail:!0}));const a=Components.Linkifier.Linkifier.linkifyURL(e);this.manifestLink=a,a.tabIndex=0,this.reportView.setURL(a),this.errorsSection.clearContent(),this.errorsSection.element.classList.toggle("hidden",!i.length);for(const e of i){const t=UI.UIUtils.createIconLabel({title:e.message,iconName:e.critical?"cross-circle-filled":"warning-filled",color:e.critical?"var(--icon-error)":"var(--icon-warning)"});this.errorsSection.appendRow().appendChild(t)}if(!t)return;65279===t.charCodeAt(0)&&(t=t.slice(1));const l=JSON.parse(t);this.nameField.textContent=N("name"),this.shortNameField.textContent=N("short_name");const d=[],c=N("description");this.descriptionField.textContent=c,c.length>324&&d.push(i18nString(UIStrings.descriptionMayBeTruncated));const p=N("start_url");if(r&&s){const e=this.identitySection.appendField(i18nString(UIStrings.computedAppId));UI.ARIAUtils.setLabel(e,"App Id"),e.textContent=r;const t=new IconButton.Icon.Icon;if(t.data={iconName:"help",color:"var(--icon-default)",width:"16px",height:"16px"},t.classList.add("inline-icon"),t.title=i18nString(UIStrings.appIdExplainer),t.tabIndex=0,e.appendChild(t),e.appendChild(UI.XLink.XLink.create("https://developer.chrome.com/blog/pwa-manifest-id/",i18nString(UIStrings.learnMore))),!N("id")){const t=e.createChild("div","multiline-value"),i=document.createElement("b");i.textContent=i18nString(UIStrings.note);const n=document.createElement("code");n.textContent="id";const o=document.createElement("code");o.textContent="id";const r=document.createElement("code");r.textContent="start_url";const a=document.createElement("code");a.textContent=s;const l=new IconButton.IconButton.IconButton;l.title=i18nString(UIStrings.copyToClipboard),l.data={groups:[{iconName:"copy",iconHeight:"12px",iconWidth:"12px",text:"",iconColor:"var(--icon-default-hover)"}],clickHandler:()=>{UI.ARIAUtils.alert(i18nString(UIStrings.copiedToClipboard,{PH1:s})),Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(s)},compact:!0,accessibleName:i18nString(UIStrings.copyToClipboard)},t.appendChild(i18n.i18n.getFormatLocalizedString(str_,UIStrings.appIdNote,{PH1:i,PH2:n,PH3:r,PH4:o,PH5:a,PH6:l}))}}else this.identitySection.removeField(i18nString(UIStrings.computedAppId));if(this.startURLField.removeChildren(),p){const t=Common.ParsedURL.ParsedURL.completeURL(e,p);if(t){const e=Components.Linkifier.Linkifier.linkifyURL(t,{text:p});e.tabIndex=0,this.startURLField.appendChild(e)}}this.themeColorSwatch.classList.toggle("hidden",!N("theme_color"));const h=Common.Color.parse(N("theme_color")||"white")||Common.Color.parse("white");h&&this.themeColorSwatch.renderColor(h,!0),this.backgroundColorSwatch.classList.toggle("hidden",!N("background_color"));const S=Common.Color.parse(N("background_color")||"white")||Common.Color.parse("white");S&&this.backgroundColorSwatch.renderColor(S,!0);const g=((l.user_preferences||{}).color_scheme||{}).dark||{},m=g.theme_color,u="string"==typeof m;if(this.darkThemeColorField.parentElement?.classList.toggle("hidden",!u),u){const e=Common.Color.parse(m);e&&this.darkThemeColorSwatch.renderColor(e,!0)}const f=g.background_color,I="string"==typeof f;if(this.darkBackgroundColorField.parentElement?.classList.toggle("hidden",!I),I){const e=Common.Color.parse(f);e&&this.darkBackgroundColorSwatch.renderColor(e,!0)}this.orientationField.textContent=N("orientation");const w=N("display");this.displayField.textContent=w;const y=(l.note_taking||{}).new_note_url,C="string"==typeof y;if(this.newNoteUrlField.parentElement?.classList.toggle("hidden",!C),this.newNoteUrlField.removeChildren(),C){const t=Common.ParsedURL.ParsedURL.completeURL(e,y),i=Components.Linkifier.Linkifier.linkifyURL(t,{text:y});i.tabIndex=0,this.newNoteUrlField.appendChild(i)}const U=l.protocol_handlers||[];this.protocolHandlersView.data={protocolHandlers:U,manifestLink:e};const P=l.icons||[];this.iconsSection.clearContent();const k=l.shortcuts||[];for(const e of this.shortcutSections)e.detach(!0);const H=l.screenshots||[];for(const e of this.screenshotsSections)e.detach(!0);const b=[],L=UI.UIUtils.CheckboxLabel.create(i18nString(UIStrings.showOnlyTheMinimumSafeAreaFor));L.classList.add("mask-checkbox"),L.addEventListener("click",(()=>{this.iconsSection.setIconMasked(L.checkboxElement.checked)})),this.iconsSection.appendRow().appendChild(L);const v=UI.XLink.XLink.create("https://web.dev/maskable-icon/",i18nString(UIStrings.documentationOnMaskableIcons));this.iconsSection.appendRow().appendChild(i18n.i18n.getFormatLocalizedString(str_,UIStrings.needHelpReadOurS,{PH1:v}));let F=!1;for(const t of P){const i=await this.appendImageResourceToSection(e,t,this.iconsSection,!1);b.push(...i.imageResourceErrors),F=i.squareSizedIconAvailable||F}F||b.push(i18nString(UIStrings.sSShouldHaveSquareIcon));let M=1;for(const t of k){const i=this.reportView.appendSection(i18nString(UIStrings.shortcutS,{PH1:M}));this.shortcutSections.push(i),i.appendFlexedField("Name",t.name),t.short_name&&i.appendFlexedField("Short name",t.short_name),t.description&&i.appendFlexedField("Description",t.description);const n=i.appendFlexedField("URL"),o=Common.ParsedURL.ParsedURL.completeURL(e,t.url),r=Components.Linkifier.Linkifier.linkifyURL(o,{text:t.url});r.tabIndex=0,n.appendChild(r);const s=t.icons||[];let a=!1;for(const t of s){const{imageResourceErrors:n}=await this.appendImageResourceToSection(e,t,i,!1);if(b.push(...n),!a&&t.sizes){const e=t.sizes.match(/^(\d+)x(\d+)$/);e&&e[1]>=96&&e[2]>=96&&(a=!0)}}a||b.push(i18nString(UIStrings.shortcutSShouldIncludeAXPixel,{PH1:M})),M++}let A=1;for(const t of H){const i=this.reportView.appendSection(i18nString(UIStrings.screenshotS,{PH1:A}));this.screenshotsSections.push(i);const{imageResourceErrors:n}=await this.appendImageResourceToSection(e,t,i,!0);b.push(...n),A++}this.installabilitySection.clearContent(),this.installabilitySection.element.classList.toggle("hidden",!n.length);const x=this.getInstallabilityErrorMessages(n);for(const e of x){const t=UI.UIUtils.createIconLabel({title:e,iconName:"warning-filled",color:"var(--icon-warning)"});this.installabilitySection.appendRow().appendChild(t)}this.errorsSection.element.classList.toggle("hidden",!i.length&&!b.length&&!d.length);for(const e of d){const t=UI.UIUtils.createIconLabel({title:e,iconName:"warning-filled",color:"var(--icon-warning)"});this.errorsSection.appendRow().appendChild(t)}for(const e of b){const t=UI.UIUtils.createIconLabel({title:e,iconName:"warning-filled",color:"var(--icon-warning)"});this.errorsSection.appendRow().appendChild(t)}function N(e){const t=l[e];return"string"!=typeof t?"":t}this.windowsControlsOverlaySection.clearContent();const R=(l.display_override||[]).includes("window-controls-overlay"),T=UI.XLink.XLink.create("https://developer.mozilla.org/en-US/docs/Web/Manifest/display_override",i18nString(UIStrings.displayOverride)),E=document.createElement("code");E.appendChild(T);const z=this.windowsControlsOverlaySection.appendRow();if(R){const e=new IconButton.Icon.Icon;e.data={iconName:"check-circle",color:"var(--icon-checkmark-green)",width:"16px",height:"16px"},e.classList.add("inline-icon"),e.tabIndex=0,z.appendChild(e);const t=document.createElement("code");t.classList.add("wco"),t.textContent="window-controls-overlay",z.appendChild(i18n.i18n.getFormatLocalizedString(str_,UIStrings.wcoFound,{PH1:t,PH2:E,PH3:this.manifestLink}))}else{const e=new IconButton.Icon.Icon;e.data={iconName:"info",color:"var(--icon-default)",width:"16px",height:"16px"},e.classList.add("inline-icon"),e.tabIndex=0,z.appendChild(e),z.appendChild(i18n.i18n.getFormatLocalizedString(str_,UIStrings.wcoNotFound,{PH1:E}))}const W=UI.XLink.XLink.create("https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/window-controls-overlay",i18nString(UIStrings.customizePwaTitleBar));this.windowsControlsOverlaySection.appendRow().appendChild(i18n.i18n.getFormatLocalizedString(str_,UIStrings.wcoNeedHelpReadMore,{PH1:W}))}getInstallabilityErrorMessages(e){const t=[];for(const i of e){let e;switch(i.errorId){case"not-in-main-frame":e=i18nString(UIStrings.pageIsNotLoadedInTheMainFrame);break;case"not-from-secure-origin":e=i18nString(UIStrings.pageIsNotServedFromASecureOrigin);break;case"no-manifest":e=i18nString(UIStrings.pageHasNoManifestLinkUrl);break;case"manifest-empty":e=i18nString(UIStrings.manifestCouldNotBeFetchedIsEmpty);break;case"start-url-not-valid":e=i18nString(UIStrings.manifestStartUrlIsNotValid);break;case"manifest-missing-name-or-short-name":e=i18nString(UIStrings.manifestDoesNotContainANameOr);break;case"manifest-display-not-supported":e=i18nString(UIStrings.manifestDisplayPropertyMustBeOne);break;case"manifest-missing-suitable-icon":if(1!==i.errorArguments.length||"minimum-icon-size-in-pixels"!==i.errorArguments[0].name){console.error("Installability error does not have the correct errorArguments");break}e=i18nString(UIStrings.manifestDoesNotContainASuitable,{PH1:i.errorArguments[0].value});break;case"no-acceptable-icon":if(1!==i.errorArguments.length||"minimum-icon-size-in-pixels"!==i.errorArguments[0].name){console.error("Installability error does not have the correct errorArguments");break}e=i18nString(UIStrings.noSuppliedIconIsAtLeastSpxSquare,{PH1:i.errorArguments[0].value});break;case"cannot-download-icon":e=i18nString(UIStrings.couldNotDownloadARequiredIcon);break;case"no-icon-available":e=i18nString(UIStrings.downloadedIconWasEmptyOr);break;case"platform-not-supported-on-android":e=i18nString(UIStrings.theSpecifiedApplicationPlatform);break;case"no-id-specified":e=i18nString(UIStrings.noPlayStoreIdProvided);break;case"ids-do-not-match":e=i18nString(UIStrings.thePlayStoreAppUrlAndPlayStoreId);break;case"already-installed":e=i18nString(UIStrings.theAppIsAlreadyInstalled);break;case"url-not-supported-for-webapk":e=i18nString(UIStrings.aUrlInTheManifestContainsA);break;case"in-incognito":e=i18nString(UIStrings.pageIsLoadedInAnIncognitoWindow);break;case"not-offline-capable":e=i18nString(UIStrings.pageDoesNotWorkOffline);break;case"no-url-for-service-worker":e=i18nString(UIStrings.couldNotCheckServiceWorker);break;case"prefer-related-applications":e=i18nString(UIStrings.manifestSpecifies);break;case"prefer-related-applications-only-beta-stable":e=i18nString(UIStrings.preferrelatedapplicationsIsOnly);break;case"manifest-display-override-not-supported":e=i18nString(UIStrings.manifestContainsDisplayoverride);break;case"warn-not-offline-capable":e=i18nString(UIStrings.pageDoesNotWorkOfflineThePage,{PH1:"https://developer.chrome.com/blog/improved-pwa-offline-detection/"});break;default:console.error(`Installability error id '${i.errorId}' is not recognized`)}e&&t.push(e)}return t}async loadImage(e){const t=document.createElement("div");t.classList.add("image-wrapper");const i=document.createElement("img"),n=new Promise(((e,t)=>{i.onload=e,i.onerror=t}));i.src=e,i.alt=i18nString(UIStrings.imageFromS,{PH1:e}),t.appendChild(i);try{return await n,{wrapper:t,image:i}}catch(e){}return null}parseSizes(e,t,i,n){const o=e.split(/\s+/),r=[];for(const e of o){if("any"===e){r.find((e=>"any"in e))||r.push({any:"any",formatted:"any"});continue}const o=e.match(/^(?<width>\d+)[xX](?<height>\d+)$/);if(o){const e=parseInt(o.groups?.width||"",10),t=parseInt(o.groups?.height||"",10),i=`${e}×${t}px`;r.push({width:e,height:t,formatted:i})}else n.push(i18nString(UIStrings.sSShouldSpecifyItsSizeAs,{PH1:t,PH2:i}))}return r}checkSizeProblem(e,t,i,n,o){if("any"in e)return{hasSquareSize:i.naturalWidth===i.naturalHeight};const r=e.width===e.height;return i.naturalWidth!==e.width&&i.naturalHeight!==e.height?{error:i18nString(UIStrings.actualSizeSspxOfSSDoesNotMatch,{PH1:i.naturalWidth,PH2:i.naturalHeight,PH3:n,PH4:o,PH5:e.width,PH6:e.height}),hasSquareSize:r}:i.naturalWidth!==e.width?{error:i18nString(UIStrings.actualWidthSpxOfSSDoesNotMatch,{PH1:i.naturalWidth,PH2:n,PH3:o,PH4:e.width}),hasSquareSize:r}:i.naturalHeight!==e.height?{error:i18nString(UIStrings.actualHeightSpxOfSSDoesNotMatch,{PH1:i.naturalHeight,PH2:n,PH3:o,PH4:e.height}),hasSquareSize:r}:{hasSquareSize:r}}async appendImageResourceToSection(e,t,i,n){const o=[],r=i18nString(n?UIStrings.screenshot:UIStrings.icon);if(!t.src)return o.push(i18nString(UIStrings.sSrcIsNotSet,{PH1:r})),{imageResourceErrors:o};const s=Common.ParsedURL.ParsedURL.completeURL(e,t.src);if(!s)return o.push(i18nString(UIStrings.sUrlSFailedToParse,{PH1:r,PH2:t.src})),{imageResourceErrors:o};const a=await this.loadImage(s);if(!a)return o.push(i18nString(UIStrings.sSFailedToLoad,{PH1:r,PH2:s})),{imageResourceErrors:o};const{wrapper:l,image:d}=a,c=this.parseSizes(t.sizes,r,s,o),p=c.map((e=>e.formatted)).join(" ")+"\n"+(t.type||""),h=i.appendFlexedField(p);let S=!1;if(t.sizes){n&&c.length>0&&"any"in c[0]&&o.push(i18nString(UIStrings.screenshotPixelSize,{url:s}));for(const e of c){const{error:i,hasSquareSize:a}=this.checkSizeProblem(e,t.type,d,r,s);if(S=S||a,i)o.push(i);else if(n){const t="any"in e?d.naturalWidth:e.width,i="any"in e?d.naturalHeight:e.height;t<320||i<320?o.push(i18nString(UIStrings.sSSizeShouldBeAtLeast320,{PH1:r,PH2:s})):t>3840||i>3840?o.push(i18nString(UIStrings.sSSizeShouldBeAtMost3840,{PH1:r,PH2:s})):t>2.3*i?o.push(i18nString(UIStrings.sSWidthDoesNotComplyWithRatioRequirement,{PH1:r,PH2:s})):i>2.3*t&&o.push(i18nString(UIStrings.sSHeightDoesNotComplyWithRatioRequirement,{PH1:r,PH2:s}))}}}else o.push(i18nString(UIStrings.sSDoesNotSpecifyItsSizeInThe,{PH1:r,PH2:s}));d.width=d.naturalWidth;const g="string"==typeof t.purpose?t.purpose.toLowerCase():"";return g.includes("any")&&g.includes("maskable")&&o.push(i18nString(UIStrings.avoidPurposeAnyAndMaskable)),h.appendChild(l),{imageResourceErrors:o,squareSizedIconAvailable:S}}wasShown(){super.wasShown(),this.reportView.registerCSSFiles([appManifestViewStyles]),this.registerCSSFiles([appManifestViewStyles])}}