chrome-devtools-frontend 1.0.1669021 → 1.0.1672557
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/fixing-skipped-tests/SKILL.md +6 -6
- package/.agents/skills/gerrit-cli/SKILL.md +4 -10
- package/.agents/skills/gerrit-cli/references/commands.md +45 -2
- package/.agents/skills/gerrit-cli/references/workflows.md +7 -0
- package/.agents/skills/gerrit-cli/scripts/import_upstream.py +34 -152
- package/config/typescript/tsconfig.eslint.json +1 -1
- package/docs/contributing/settings-experiments-features.md +2 -8
- package/docs/ecosystem/automatic_workspace_folders.md +0 -19
- package/eslint.config.mjs +5 -5
- package/front_end/core/common/Lazy.ts +3 -3
- package/front_end/core/common/SettingRegistration.ts +0 -7
- package/front_end/core/common/Settings.ts +0 -38
- package/front_end/core/host/UserMetrics.ts +187 -953
- package/front_end/core/host/UserMetricsEnums.ts +949 -0
- package/front_end/core/root/Runtime.ts +21 -138
- package/front_end/core/sdk/CSSMetadata.ts +70 -65
- package/front_end/core/sdk/CategorizedBreakpoint.ts +0 -1
- package/front_end/core/sdk/ChildTargetManager.ts +0 -2
- package/front_end/core/sdk/EmulationModel.ts +0 -2
- package/front_end/core/sdk/EventBreakpointsModel.ts +0 -4
- package/front_end/core/sdk/NetworkManager.ts +0 -3
- package/front_end/core/sdk/PageResourceLoader.ts +9 -9
- package/front_end/core/sdk/RehydratingConnection.ts +52 -4
- package/front_end/core/sdk/Target.ts +0 -4
- package/front_end/devtools_compatibility.js +886 -0
- package/front_end/entrypoints/inspector_main/RenderingOptions.ts +7 -6
- package/front_end/entrypoints/main/ExecutionContextSelector.ts +0 -1
- package/front_end/entrypoints/main/MainImpl.ts +18 -22
- package/front_end/foundation/Universe.ts +7 -2
- package/front_end/generated/InspectorBackendCommands.ts +3 -10
- package/front_end/generated/{SupportedCSSProperties.js → SupportedCSSProperties.ts} +16 -0
- package/front_end/generated/protocol-mapping.d.ts +0 -42
- package/front_end/generated/protocol-proxy-api.d.ts +0 -38
- package/front_end/generated/protocol.ts +9 -169
- package/front_end/models/ai_assistance/AiAgent2.ts +11 -3
- package/front_end/models/ai_assistance/AiConversation.ts +1 -0
- package/front_end/models/ai_assistance/AiHistoryStorage.ts +8 -5
- package/front_end/models/ai_assistance/AiSetting.ts +108 -0
- package/front_end/models/ai_assistance/AiUtils.ts +47 -0
- package/front_end/models/ai_assistance/ChangeManager.ts +1 -0
- package/front_end/models/ai_assistance/ExtensionScope.ts +3 -12
- package/front_end/models/ai_assistance/agents/AiAgent.ts +11 -18
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +3 -0
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +42 -17
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +3 -2
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +253 -155
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
- package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +12 -6
- package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +3 -1
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +1 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +4 -3
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +1 -0
- package/front_end/models/ai_assistance/injected.ts +1 -0
- package/front_end/models/ai_assistance/performance/AICallTree.ts +1 -0
- package/front_end/models/ai_assistance/skills/Skill.ts +1 -1
- package/front_end/models/ai_assistance/skills/SkillRegistry.ts +2 -0
- package/front_end/models/ai_assistance/skills/performance.md +10 -0
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +52 -5
- package/front_end/models/ai_assistance/tools/GetElementAccessibilityDetails.ts +4 -4
- package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +4 -4
- package/front_end/models/ai_assistance/tools/GetNetworkRequestDetails.ts +5 -4
- package/front_end/models/ai_assistance/tools/GetStyles.ts +5 -4
- package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +5 -4
- package/front_end/models/ai_assistance/tools/README.md +1 -1
- package/front_end/models/ai_assistance/tools/RecordPerformanceTrace.ts +63 -0
- package/front_end/models/ai_assistance/tools/ResolveDevtoolsNodePath.ts +5 -5
- package/front_end/models/ai_assistance/tools/Tool.ts +118 -24
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +2 -0
- package/front_end/models/badges/UserBadges.ts +2 -0
- package/front_end/models/bindings/NetworkProject.ts +5 -0
- package/front_end/models/bindings/ResourceScriptMapping.ts +2 -0
- package/front_end/models/bindings/ResourceUtils.ts +3 -0
- package/front_end/models/crux-manager/CrUXManager.ts +1 -0
- package/front_end/models/emulation/DeviceModeModel.ts +140 -7
- package/front_end/models/emulation/EmulatedDevices.ts +246 -793
- package/front_end/models/issues_manager/IssuesManager.ts +10 -2
- package/front_end/models/live-metrics/LiveMetrics.ts +41 -9
- package/front_end/models/logs/LogManager.ts +8 -5
- package/front_end/models/logs/NetworkLog.ts +1 -0
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +21 -3
- package/front_end/models/persistence/NetworkPersistenceManager.ts +6 -0
- package/front_end/models/project_settings/ProjectSettingsModel.ts +8 -12
- package/front_end/models/trace/Processor.ts +42 -10
- package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +12 -19
- package/front_end/models/trace/handlers/MetaHandler.ts +38 -5
- package/front_end/models/trace/insights/CLSCulprits.ts +1 -2
- package/front_end/models/trace/insights/CharacterSet.ts +1 -1
- package/front_end/models/trace/insights/Common.ts +21 -2
- package/front_end/models/trace/insights/DocumentLatency.ts +1 -1
- package/front_end/models/trace/insights/LCPBreakdown.ts +7 -6
- package/front_end/models/trace/insights/LCPDiscovery.ts +1 -1
- package/front_end/models/trace/insights/ModernHTTP.ts +7 -3
- package/front_end/models/trace/insights/NetworkDependencyTree.ts +1 -1
- package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
- package/front_end/models/trace/insights/ThirdParties.ts +5 -2
- package/front_end/models/trace/insights/types.ts +11 -6
- package/front_end/models/trace/types/Configuration.ts +5 -0
- package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +3 -1
- package/front_end/models/workspace/IgnoreListManager.ts +2 -0
- package/front_end/models/workspace/UISourceCode.ts +2 -0
- package/front_end/models/workspace_diff/WorkspaceDiff.ts +4 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +22 -22
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +0 -7
- package/front_end/panels/ai_assistance/components/ChatInput.ts +4 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +79 -34
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +1 -2
- package/front_end/panels/ai_assistance/components/walkthroughView.css +1 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +9 -106
- package/front_end/panels/application/ApplicationPanelTreeElement.ts +1 -1
- package/front_end/panels/application/application.ts +0 -10
- package/front_end/panels/application/components/components.ts +0 -4
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +0 -5
- package/front_end/panels/browser_debugger/EventListenerBreakpointsSidebarPane.ts +6 -12
- package/front_end/panels/browser_debugger/browser_debugger-meta.ts +5 -3
- package/front_end/panels/console/ConsoleFormat.ts +2 -62
- package/front_end/panels/console/ConsoleViewMessage.ts +14 -7
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -2
- package/front_end/panels/emulation/AdvancedApp.ts +1 -2
- package/front_end/panels/emulation/DeviceModeToolbar.ts +83 -69
- package/front_end/panels/emulation/DeviceModeView.ts +4 -134
- package/front_end/panels/emulation/DeviceModeWrapper.ts +52 -69
- package/front_end/panels/emulation/MediaQueryInspector.ts +2 -2
- package/front_end/panels/emulation/emulation-meta.ts +12 -12
- package/front_end/panels/issues/IssuesPane.ts +3 -1
- package/front_end/panels/lighthouse/LighthouseController.ts +6 -0
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +17 -21
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryNavigator.ts +206 -126
- package/front_end/panels/linear_memory_inspector/components/linearMemoryInspector.css +1 -1
- package/front_end/panels/mobile_throttling/CalibrationController.ts +1 -1
- package/front_end/panels/mobile_throttling/MobileThrottlingSelector.ts +3 -3
- package/front_end/panels/mobile_throttling/NetworkPanelIndicator.ts +6 -6
- package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +14 -12
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +13 -13
- package/front_end/panels/mobile_throttling/ThrottlingPresets.ts +10 -10
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +28 -28
- package/front_end/panels/mobile_throttling/mobile_throttling-meta.ts +6 -6
- package/front_end/panels/network/RequestHeadersView.ts +1 -1
- package/front_end/panels/network/ResourceChunkView.ts +243 -144
- package/front_end/panels/network/ResourceDirectSocketChunkView.ts +52 -29
- package/front_end/panels/network/ResourceWebSocketFrameView.ts +21 -35
- package/front_end/panels/network/resourceChunkView.css +41 -36
- package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +21 -12
- package/front_end/panels/profiler/profiler.ts +4 -0
- package/front_end/panels/recorder/RecorderPanel.ts +6 -14
- package/front_end/panels/sensors/LocationsSettingsTab.ts +7 -7
- package/front_end/panels/settings/AISettingsTab.ts +75 -31
- package/front_end/panels/settings/SettingsScreen.ts +8 -13
- package/front_end/panels/settings/components/SyncSection.ts +3 -4
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +650 -18
- package/front_end/panels/settings/emulation/devicesSettingsTab.css +18 -0
- package/front_end/panels/settings/settings-meta.ts +0 -1
- package/front_end/panels/sources/CategorizedBreakpointL10n.ts +0 -2
- package/front_end/panels/sources/DebuggerPausedMessage.ts +11 -5
- package/front_end/panels/sources/DebuggerPlugin.ts +1 -1
- package/front_end/panels/sources/EditingLocationHistoryManager.ts +12 -9
- package/front_end/panels/sources/SourcesPanel.ts +19 -17
- package/front_end/panels/sources/SourcesView.ts +191 -96
- package/front_end/panels/sources/TabbedEditorContainer.ts +3 -4
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +2 -5
- package/front_end/panels/timeline/TimelinePanel.ts +2 -0
- package/front_end/panels/timeline/TimelineUIUtils.ts +15 -0
- package/front_end/panels/timeline/components/CWVMetrics.ts +16 -3
- package/front_end/panels/timeline/components/cwvMetrics.css +4 -0
- package/front_end/panels/timeline/components/liveMetricsView.css +0 -17
- package/front_end/panels/timeline/components/metricValueStyles.css +17 -0
- package/front_end/panels/timeline/timeline-meta.ts +3 -5
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror.next/chunk/angular.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/java.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/java.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/legacy.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/less.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/less.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/markdown.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/php.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/php.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/python.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/sass.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/sass.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/svelte.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/svelte.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/vue.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js.map +1 -1
- package/front_end/third_party/codemirror.next/codemirror.next.d.ts +1332 -193
- package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
- package/front_end/third_party/codemirror.next/rebuild.sh +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +64 -15
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +65 -16
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +50 -7
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js +5 -5
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.js +8 -6
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Dialog.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Dialog.js +3 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Dialog.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +16 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.js +11 -6
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Dialog.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Dialog.js +5 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Dialog.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +10 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js +4 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts +27 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js +12 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.js +2 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js +5 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +64 -15
- package/front_end/third_party/puppeteer/package/package.json +2 -2
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +50 -7
- package/front_end/third_party/puppeteer/package/src/bidi/BidiOverCdp.ts +9 -7
- package/front_end/third_party/puppeteer/package/src/bidi/Connection.ts +9 -6
- package/front_end/third_party/puppeteer/package/src/bidi/Dialog.ts +4 -0
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +24 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Connection.ts +11 -6
- package/front_end/third_party/puppeteer/package/src/cdp/Dialog.ts +7 -0
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +11 -0
- package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +7 -3
- package/front_end/third_party/puppeteer/package/src/common/Debug.ts +30 -5
- package/front_end/third_party/puppeteer/package/src/common/util.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +2 -0
- package/front_end/third_party/puppeteer/package/src/node/ScreenRecorder.ts +6 -4
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/tsconfig.compatibility.json +2 -1
- package/front_end/tsconfig.json +1 -1
- package/front_end/ui/components/icon_button/IconButton.ts +1 -1
- package/front_end/ui/components/issue_counter/IssueCounter.ts +1 -1
- package/front_end/ui/components/settings/SettingCheckbox.ts +4 -7
- package/front_end/ui/components/settings/settings.ts +1 -2
- package/front_end/ui/legacy/Treeoutline.ts +52 -30
- package/front_end/ui/legacy/components/object_ui/CSSStyleSanitizer.ts +74 -0
- package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +6 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +47 -54
- package/front_end/ui/legacy/components/object_ui/object_ui.ts +2 -0
- package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +5 -27
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +10 -12
- package/front_end/ui/settings/SettingUIRegistration.ts +0 -8
- package/front_end/ui/visual_logging/KnownContextValues.ts +37 -0
- package/inspector_overlay/tsconfig.json +8 -2
- package/package.json +3 -2
- package/.agents/skills/gerrit-cli/scripts/gerrit_client_wrapper.py +0 -47
- package/front_end/core/sdk/CSSModel.test.api.ts +0 -102
- package/front_end/core/sdk/DOMModel.test.api.ts +0 -104
- package/front_end/foundation/Universe.test.api.ts +0 -73
- package/front_end/panels/application/SharedStorageEventsView.ts +0 -128
- package/front_end/panels/application/SharedStorageItemsView.ts +0 -179
- package/front_end/panels/application/SharedStorageListTreeElement.ts +0 -65
- package/front_end/panels/application/SharedStorageModel.ts +0 -249
- package/front_end/panels/application/SharedStorageTreeElement.ts +0 -40
- package/front_end/panels/application/components/SharedStorageAccessGrid.ts +0 -191
- package/front_end/panels/application/components/SharedStorageMetadataView.ts +0 -133
- package/front_end/panels/application/components/sharedStorageAccessGrid.css +0 -29
- package/front_end/panels/application/components/sharedStorageMetadataView.css +0 -29
- package/front_end/panels/application/sharedStorageEventsView.css +0 -9
- package/front_end/panels/network/OriginalResourceChunkView.ts +0 -340
- package/front_end/panels/network/originalResourceChunkView.css +0 -49
- package/front_end/ui/components/settings/SettingDeprecationWarning.ts +0 -47
- package/front_end/ui/components/settings/settingDeprecationWarning.css +0 -14
- /package/front_end/generated/{ARIAProperties.js → ARIAProperties.ts} +0 -0
|
@@ -74,17 +74,188 @@ const UIStrings = {
|
|
|
74
74
|
* @description Error message in the Devices settings tab shown when the user agent string is empty.
|
|
75
75
|
*/
|
|
76
76
|
userAgentStringCannotBeEmpty: 'User agent string can’t be empty.',
|
|
77
|
+
/**
|
|
78
|
+
* @description Label for portrait safe-area values on a custom device.
|
|
79
|
+
*/
|
|
80
|
+
portraitSafeArea: 'Portrait safe area',
|
|
81
|
+
/**
|
|
82
|
+
* @description Label for landscape safe-area values on a custom device.
|
|
83
|
+
*/
|
|
84
|
+
landscapeSafeArea: 'Landscape safe area',
|
|
85
|
+
/**
|
|
86
|
+
* @description Placeholder text for a custom device safe-area left inset field.
|
|
87
|
+
*/
|
|
88
|
+
safeAreaLeft: 'Left inset',
|
|
89
|
+
/**
|
|
90
|
+
* @description Placeholder text for a custom device safe-area top inset field.
|
|
91
|
+
*/
|
|
92
|
+
safeAreaTop: 'Top inset',
|
|
93
|
+
/**
|
|
94
|
+
* @description Placeholder text for a custom device safe-area right inset field.
|
|
95
|
+
*/
|
|
96
|
+
safeAreaRight: 'Right inset',
|
|
97
|
+
/**
|
|
98
|
+
* @description Placeholder text for a custom device safe-area bottom inset field.
|
|
99
|
+
*/
|
|
100
|
+
safeAreaBottom: 'Bottom inset',
|
|
101
|
+
/**
|
|
102
|
+
* @description Error message shown when a custom device safe-area value is invalid.
|
|
103
|
+
* @example {Portrait safe area} PH1
|
|
104
|
+
* @example {Top inset} PH2
|
|
105
|
+
* @example {9999} PH3
|
|
106
|
+
*/
|
|
107
|
+
safeAreaValueMustBeInRange: '{PH1}: {PH2} must be an integer from 0 to {PH3}.',
|
|
108
|
+
/**
|
|
109
|
+
* @description Error message shown when custom device safe-area left and right insets are too large.
|
|
110
|
+
* @example {Portrait safe area} PH1
|
|
111
|
+
*/
|
|
112
|
+
safeAreaHorizontalInsetsExceedWidth: '{PH1}: Left and right insets must not exceed the device width.',
|
|
113
|
+
/**
|
|
114
|
+
* @description Error message shown when custom device safe-area top and bottom insets are too large.
|
|
115
|
+
* @example {Landscape safe area} PH1
|
|
116
|
+
*/
|
|
117
|
+
safeAreaVerticalInsetsExceedHeight: '{PH1}: Top and bottom insets must not exceed the device height.',
|
|
118
|
+
/**
|
|
119
|
+
* @description Label for display cutout values on a custom device.
|
|
120
|
+
*/
|
|
121
|
+
displayCutout: 'Display cutout',
|
|
122
|
+
/**
|
|
123
|
+
* @description Option shown when a custom device has no display cutout.
|
|
124
|
+
*/
|
|
125
|
+
noDisplayCutout: 'No cutout',
|
|
126
|
+
/**
|
|
127
|
+
* @description Option shown for pill-shaped display cutouts such as Dynamic Island.
|
|
128
|
+
*/
|
|
129
|
+
pillDisplayCutout: 'Pill',
|
|
130
|
+
/**
|
|
131
|
+
* @description Option shown for classic notch display cutouts.
|
|
132
|
+
*/
|
|
133
|
+
notchDisplayCutout: 'Notch',
|
|
134
|
+
/**
|
|
135
|
+
* @description Option shown for circular display cutouts such as hole-punch cameras.
|
|
136
|
+
*/
|
|
137
|
+
circleDisplayCutout: 'Circle',
|
|
138
|
+
/**
|
|
139
|
+
* @description Option shown for rectangular display cutouts.
|
|
140
|
+
*/
|
|
141
|
+
rectangleDisplayCutout: 'Rectangle',
|
|
142
|
+
/**
|
|
143
|
+
* @description Placeholder text for a custom device display cutout x coordinate field.
|
|
144
|
+
*/
|
|
145
|
+
cutoutX: 'Cutout x',
|
|
146
|
+
/**
|
|
147
|
+
* @description Placeholder text for a custom device display cutout y coordinate field.
|
|
148
|
+
*/
|
|
149
|
+
cutoutY: 'Cutout y',
|
|
150
|
+
/**
|
|
151
|
+
* @description Placeholder text for a custom device display cutout width field.
|
|
152
|
+
*/
|
|
153
|
+
cutoutWidth: 'Cutout width',
|
|
154
|
+
/**
|
|
155
|
+
* @description Placeholder text for a custom device display cutout height field.
|
|
156
|
+
*/
|
|
157
|
+
cutoutHeight: 'Cutout height',
|
|
158
|
+
/**
|
|
159
|
+
* @description Placeholder text for a custom device pill-shaped display cutout radius field.
|
|
160
|
+
*/
|
|
161
|
+
cutoutBorderRadius: 'Pill radius',
|
|
162
|
+
/**
|
|
163
|
+
* @description Placeholder text for a custom device notch upper radius field.
|
|
164
|
+
*/
|
|
165
|
+
cutoutUpperRadius: 'Upper radius',
|
|
166
|
+
/**
|
|
167
|
+
* @description Placeholder text for a custom device notch lower radius field.
|
|
168
|
+
*/
|
|
169
|
+
cutoutLowerRadius: 'Lower radius',
|
|
170
|
+
/**
|
|
171
|
+
* @description Placeholder text for a custom device circular display cutout center x coordinate field.
|
|
172
|
+
*/
|
|
173
|
+
cutoutCenterX: 'Center x',
|
|
174
|
+
/**
|
|
175
|
+
* @description Placeholder text for a custom device circular display cutout center y coordinate field.
|
|
176
|
+
*/
|
|
177
|
+
cutoutCenterY: 'Center y',
|
|
178
|
+
/**
|
|
179
|
+
* @description Placeholder text for a custom device circular display cutout radius field.
|
|
180
|
+
*/
|
|
181
|
+
cutoutRadius: 'Radius',
|
|
182
|
+
/**
|
|
183
|
+
* @description Error message shown when a custom display cutout field is required.
|
|
184
|
+
* @example {Cutout width} PH1
|
|
185
|
+
*/
|
|
186
|
+
cutoutFieldRequired: '{PH1} is required when display cutout is enabled.',
|
|
187
|
+
/**
|
|
188
|
+
* @description Error message shown when a custom display cutout field is outside its supported integer range.
|
|
189
|
+
* @example {Cutout x} PH1
|
|
190
|
+
* @example {9999} PH2
|
|
191
|
+
*/
|
|
192
|
+
cutoutValueMustBeInRange: '{PH1} must be an integer from 0 to {PH2}.',
|
|
193
|
+
/**
|
|
194
|
+
* @description Error message shown when a custom display cutout field must be positive.
|
|
195
|
+
* @example {Cutout width} PH1
|
|
196
|
+
*/
|
|
197
|
+
cutoutValueMustBePositiveInteger: '{PH1} must be a positive integer.',
|
|
198
|
+
/**
|
|
199
|
+
* @description Error message shown when a custom display cutout's x coordinate plus its width exceeds the device width.
|
|
200
|
+
*/
|
|
201
|
+
cutoutXAndWidthExceedDeviceWidth: 'Cutout x plus width must not exceed the device width.',
|
|
202
|
+
/**
|
|
203
|
+
* @description Error message shown when a custom display cutout's y coordinate plus its height exceeds the device height.
|
|
204
|
+
*/
|
|
205
|
+
cutoutYAndHeightExceedDeviceHeight: 'Cutout y plus height must not exceed the device height.',
|
|
206
|
+
/**
|
|
207
|
+
* @description Error message shown when a circular display cutout is outside its cutout bounds.
|
|
208
|
+
*/
|
|
209
|
+
circleMustFitCutoutBounds: 'Circle must fit within the cutout bounds.',
|
|
77
210
|
} as const;
|
|
78
211
|
const str_ = i18n.i18n.registerUIStrings('panels/settings/emulation/DevicesSettingsTab.ts', UIStrings);
|
|
79
212
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
80
213
|
|
|
214
|
+
function parseOptionalNonNegativeInteger(value: string): number|null {
|
|
215
|
+
const trimmedValue = value.trim();
|
|
216
|
+
if (!trimmedValue) {
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
if (!/^\d+$/.test(trimmedValue)) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const parsedValue = Number(trimmedValue);
|
|
223
|
+
if (!Number.isSafeInteger(parsedValue) || parsedValue < 0 ||
|
|
224
|
+
parsedValue > EmulationModel.DeviceModeModel.MaxDeviceSize) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
return parsedValue;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const NO_CUSTOM_CUTOUT = 'none';
|
|
231
|
+
|
|
232
|
+
type DeviceEditorValidator = (item: EmulationModel.EmulatedDevices.EmulatedDevice, index: number,
|
|
233
|
+
input: UI.ListWidget.EditorControl) => UI.ListWidget.ValidatorResult;
|
|
234
|
+
|
|
235
|
+
interface CutoutFieldValidators {
|
|
236
|
+
shape: DeviceEditorValidator;
|
|
237
|
+
x: DeviceEditorValidator;
|
|
238
|
+
y: DeviceEditorValidator;
|
|
239
|
+
width: DeviceEditorValidator;
|
|
240
|
+
height: DeviceEditorValidator;
|
|
241
|
+
pillRadius: DeviceEditorValidator;
|
|
242
|
+
notchUpperRadius: DeviceEditorValidator;
|
|
243
|
+
notchLowerRadius: DeviceEditorValidator;
|
|
244
|
+
circleCenterX: DeviceEditorValidator;
|
|
245
|
+
circleCenterY: DeviceEditorValidator;
|
|
246
|
+
circleRadius: DeviceEditorValidator;
|
|
247
|
+
}
|
|
248
|
+
|
|
81
249
|
export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
82
250
|
UI.ListWidget.Delegate<EmulationModel.EmulatedDevices.EmulatedDevice> {
|
|
83
251
|
containerElement: HTMLElement;
|
|
84
252
|
private readonly addCustomButton: Buttons.Button.Button;
|
|
85
253
|
private readonly ariaSuccessMessageElement: HTMLElement;
|
|
86
254
|
readonly #customDeviceList: UI.ListWidget.ListWidget<EmulationModel.EmulatedDevices.EmulatedDevice>;
|
|
87
|
-
readonly #
|
|
255
|
+
readonly #defaultDeviceLists = new Map<EmulationModel.EmulatedDevices.Category, {
|
|
256
|
+
container: HTMLElement,
|
|
257
|
+
list: UI.ListWidget.ListWidget<EmulationModel.EmulatedDevices.EmulatedDevice>,
|
|
258
|
+
}>();
|
|
88
259
|
private muteUpdate: boolean;
|
|
89
260
|
private emulatedDevicesList: EmulationModel.EmulatedDevices.EmulatedDevicesList;
|
|
90
261
|
private editor?: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>;
|
|
@@ -97,10 +268,6 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
97
268
|
this.contentElement.createChild('div', 'settings-card-container-wrapper').createChild('div');
|
|
98
269
|
this.containerElement.classList.add('settings-card-container', 'ignore-list-settings');
|
|
99
270
|
|
|
100
|
-
this.#defaultDeviceList = new UI.ListWidget.ListWidget(this, false /* delegatesFocus */);
|
|
101
|
-
this.#defaultDeviceList.registerRequiredCSS(devicesSettingsTabStyles);
|
|
102
|
-
this.#defaultDeviceList.element.classList.add('devices-list', 'device-card-content');
|
|
103
|
-
|
|
104
271
|
this.muteUpdate = false;
|
|
105
272
|
this.emulatedDevicesList = EmulationModel.EmulatedDevices.EmulatedDevicesList.instance();
|
|
106
273
|
this.emulatedDevicesList.addEventListener(
|
|
@@ -132,7 +299,23 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
132
299
|
|
|
133
300
|
const defaultDevicesCard = this.containerElement.createChild('devtools-card');
|
|
134
301
|
defaultDevicesCard.heading = i18nString(UIStrings.defaultDevices);
|
|
135
|
-
|
|
302
|
+
|
|
303
|
+
for (const category of EmulationModel.EmulatedDevices.CATEGORY_ORDER) {
|
|
304
|
+
const groupContainer = document.createElement('div');
|
|
305
|
+
groupContainer.classList.add('device-group-container');
|
|
306
|
+
|
|
307
|
+
const groupTitle = groupContainer.createChild('div', 'device-group-title');
|
|
308
|
+
groupTitle.textContent = EmulationModel.EmulatedDevices.getCategoryTitle(category);
|
|
309
|
+
|
|
310
|
+
defaultDevicesCard.append(groupContainer);
|
|
311
|
+
|
|
312
|
+
const listWidget = new UI.ListWidget.ListWidget(this, false /* delegatesFocus */);
|
|
313
|
+
listWidget.registerRequiredCSS(devicesSettingsTabStyles);
|
|
314
|
+
listWidget.element.classList.add('devices-list', 'device-card-content');
|
|
315
|
+
listWidget.show(groupContainer);
|
|
316
|
+
|
|
317
|
+
this.#defaultDeviceLists.set(category, {container: groupContainer, list: listWidget});
|
|
318
|
+
}
|
|
136
319
|
}
|
|
137
320
|
|
|
138
321
|
override wasShown(): void {
|
|
@@ -145,18 +328,32 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
145
328
|
return;
|
|
146
329
|
}
|
|
147
330
|
|
|
148
|
-
this.#
|
|
331
|
+
for (const {list} of this.#defaultDeviceLists.values()) {
|
|
332
|
+
list.clear();
|
|
333
|
+
}
|
|
149
334
|
this.#customDeviceList.clear();
|
|
150
335
|
|
|
151
|
-
|
|
152
|
-
for (let i = 0; i <
|
|
153
|
-
this.#customDeviceList.appendItem(
|
|
336
|
+
const customDevices = this.emulatedDevicesList.custom().slice();
|
|
337
|
+
for (let i = 0; i < customDevices.length; ++i) {
|
|
338
|
+
this.#customDeviceList.appendItem(customDevices[i], true);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const standardDevices = this.emulatedDevicesList.standard().slice();
|
|
342
|
+
standardDevices.sort(EmulationModel.EmulatedDevices.EmulatedDevice.deviceComparator);
|
|
343
|
+
|
|
344
|
+
const categoryItemCounts = new Map<EmulationModel.EmulatedDevices.Category, number>();
|
|
345
|
+
for (const device of standardDevices) {
|
|
346
|
+
const cat = EmulationModel.EmulatedDevices.deviceCategory(device);
|
|
347
|
+
const group = this.#defaultDeviceLists.get(cat);
|
|
348
|
+
if (group) {
|
|
349
|
+
group.list.appendItem(device, false);
|
|
350
|
+
categoryItemCounts.set(cat, (categoryItemCounts.get(cat) || 0) + 1);
|
|
351
|
+
}
|
|
154
352
|
}
|
|
155
353
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.#defaultDeviceList.appendItem(devices[i], false);
|
|
354
|
+
for (const [cat, group] of this.#defaultDeviceLists.entries()) {
|
|
355
|
+
const count = categoryItemCounts.get(cat) || 0;
|
|
356
|
+
group.container.style.display = count > 0 ? '' : 'none';
|
|
160
357
|
}
|
|
161
358
|
}
|
|
162
359
|
|
|
@@ -185,6 +382,21 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
185
382
|
return value ? String(value) : '';
|
|
186
383
|
}
|
|
187
384
|
|
|
385
|
+
private verticalMode(device: EmulationModel.EmulatedDevices.EmulatedDevice): EmulationModel.EmulatedDevices.Mode
|
|
386
|
+
|null {
|
|
387
|
+
return device.modes.find(mode => mode.orientation === EmulationModel.EmulatedDevices.Vertical) || null;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
private horizontalMode(device: EmulationModel.EmulatedDevices.EmulatedDevice): EmulationModel.EmulatedDevices.Mode
|
|
391
|
+
|null {
|
|
392
|
+
return device.modes.find(mode => mode.orientation === EmulationModel.EmulatedDevices.Horizontal) || null;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private editorIntegerValue(editor: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>,
|
|
396
|
+
controlName: string): number {
|
|
397
|
+
return parseOptionalNonNegativeInteger(editor.control(controlName).value) ?? 0;
|
|
398
|
+
}
|
|
399
|
+
|
|
188
400
|
renderItem(device: EmulationModel.EmulatedDevices.EmulatedDevice, editable: boolean): Element {
|
|
189
401
|
const label = document.createElement('label');
|
|
190
402
|
label.classList.add('devices-list-item');
|
|
@@ -222,18 +434,32 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
222
434
|
device.deviceScaleFactor = editor.control('scale').value ? parseFloat(editor.control('scale').value) : 0;
|
|
223
435
|
device.userAgent = editor.control('user-agent').value;
|
|
224
436
|
device.modes = [];
|
|
225
|
-
|
|
437
|
+
const verticalMode: EmulationModel.EmulatedDevices.Mode = {
|
|
226
438
|
title: '',
|
|
227
439
|
orientation: EmulationModel.EmulatedDevices.Vertical,
|
|
228
440
|
insets: new EmulationModel.DeviceModeModel.Insets(0, 0, 0, 0),
|
|
229
441
|
image: null,
|
|
230
|
-
}
|
|
231
|
-
|
|
442
|
+
};
|
|
443
|
+
const safeAreaInsets = this.safeAreaInsetsFromEditor(editor);
|
|
444
|
+
if (safeAreaInsets) {
|
|
445
|
+
verticalMode.safeAreaInsets = safeAreaInsets;
|
|
446
|
+
}
|
|
447
|
+
const cutout = this.cutoutFromEditor(editor);
|
|
448
|
+
if (cutout) {
|
|
449
|
+
verticalMode.cutout = cutout;
|
|
450
|
+
}
|
|
451
|
+
device.modes.push(verticalMode);
|
|
452
|
+
const horizontalMode: EmulationModel.EmulatedDevices.Mode = {
|
|
232
453
|
title: '',
|
|
233
454
|
orientation: EmulationModel.EmulatedDevices.Horizontal,
|
|
234
455
|
insets: new EmulationModel.DeviceModeModel.Insets(0, 0, 0, 0),
|
|
235
456
|
image: null,
|
|
236
|
-
}
|
|
457
|
+
};
|
|
458
|
+
const landscapeSafeAreaInsets = this.safeAreaInsetsFromEditor(editor, 'landscape-');
|
|
459
|
+
if (landscapeSafeAreaInsets) {
|
|
460
|
+
horizontalMode.safeAreaInsets = landscapeSafeAreaInsets;
|
|
461
|
+
}
|
|
462
|
+
device.modes.push(horizontalMode);
|
|
237
463
|
device.capabilities = [];
|
|
238
464
|
const uaType = editor.control('ua-type').value;
|
|
239
465
|
if (uaType === EmulationModel.DeviceModeModel.UA.MOBILE ||
|
|
@@ -277,6 +503,8 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
277
503
|
editor.control('height').value = this.toNumericInputValue(device.vertical.height);
|
|
278
504
|
editor.control('scale').value = this.toNumericInputValue(device.deviceScaleFactor);
|
|
279
505
|
editor.control('user-agent').value = device.userAgent;
|
|
506
|
+
this.populateSafeAreaEditor(editor, device);
|
|
507
|
+
this.populateCutoutEditor(editor, device);
|
|
280
508
|
let uaType;
|
|
281
509
|
if (device.mobile()) {
|
|
282
510
|
uaType =
|
|
@@ -292,6 +520,118 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
292
520
|
return editor;
|
|
293
521
|
}
|
|
294
522
|
|
|
523
|
+
private safeAreaInsetsFromEditor(editor: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>,
|
|
524
|
+
controlPrefix = ''): EmulationModel.DeviceModeModel.Insets|null {
|
|
525
|
+
const left = this.editorIntegerValue(editor, `${controlPrefix}safe-area-left`);
|
|
526
|
+
const top = this.editorIntegerValue(editor, `${controlPrefix}safe-area-top`);
|
|
527
|
+
const right = this.editorIntegerValue(editor, `${controlPrefix}safe-area-right`);
|
|
528
|
+
const bottom = this.editorIntegerValue(editor, `${controlPrefix}safe-area-bottom`);
|
|
529
|
+
if (!left && !top && !right && !bottom) {
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
return new EmulationModel.DeviceModeModel.Insets(left, top, right, bottom);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
private cutoutFromEditor(editor: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>):
|
|
536
|
+
EmulationModel.EmulatedDevices.Cutout|null {
|
|
537
|
+
const shape = editor.control('cutout-shape').value;
|
|
538
|
+
const baseCutout = {
|
|
539
|
+
x: this.editorIntegerValue(editor, 'cutout-x'),
|
|
540
|
+
y: this.editorIntegerValue(editor, 'cutout-y'),
|
|
541
|
+
width: this.editorIntegerValue(editor, 'cutout-width'),
|
|
542
|
+
height: this.editorIntegerValue(editor, 'cutout-height'),
|
|
543
|
+
};
|
|
544
|
+
switch (shape) {
|
|
545
|
+
case EmulationModel.EmulatedDevices.CutoutShape.PILL:
|
|
546
|
+
return {
|
|
547
|
+
shape,
|
|
548
|
+
...baseCutout,
|
|
549
|
+
borderRadius: this.editorIntegerValue(editor, 'cutout-border-radius'),
|
|
550
|
+
};
|
|
551
|
+
case EmulationModel.EmulatedDevices.CutoutShape.NOTCH:
|
|
552
|
+
return {
|
|
553
|
+
shape,
|
|
554
|
+
...baseCutout,
|
|
555
|
+
upperRadius: this.editorIntegerValue(editor, 'cutout-upper-radius'),
|
|
556
|
+
lowerRadius: this.editorIntegerValue(editor, 'cutout-lower-radius'),
|
|
557
|
+
};
|
|
558
|
+
case EmulationModel.EmulatedDevices.CutoutShape.CIRCLE:
|
|
559
|
+
return {
|
|
560
|
+
shape,
|
|
561
|
+
...baseCutout,
|
|
562
|
+
cx: this.editorIntegerValue(editor, 'cutout-cx'),
|
|
563
|
+
cy: this.editorIntegerValue(editor, 'cutout-cy'),
|
|
564
|
+
radius: this.editorIntegerValue(editor, 'cutout-radius'),
|
|
565
|
+
};
|
|
566
|
+
case EmulationModel.EmulatedDevices.CutoutShape.RECTANGLE:
|
|
567
|
+
return {shape, ...baseCutout};
|
|
568
|
+
default:
|
|
569
|
+
return null;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
private populateSafeAreaEditor(editor: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>,
|
|
574
|
+
device: EmulationModel.EmulatedDevices.EmulatedDevice): void {
|
|
575
|
+
const safeAreaInsets = this.verticalMode(device)?.safeAreaInsets;
|
|
576
|
+
editor.control('safe-area-left').value = this.toNumericInputValue(safeAreaInsets?.left || 0);
|
|
577
|
+
editor.control('safe-area-top').value = this.toNumericInputValue(safeAreaInsets?.top || 0);
|
|
578
|
+
editor.control('safe-area-right').value = this.toNumericInputValue(safeAreaInsets?.right || 0);
|
|
579
|
+
editor.control('safe-area-bottom').value = this.toNumericInputValue(safeAreaInsets?.bottom || 0);
|
|
580
|
+
|
|
581
|
+
const landscapeSafeAreaInsets = this.horizontalMode(device)?.safeAreaInsets;
|
|
582
|
+
editor.control('landscape-safe-area-left').value = this.toNumericInputValue(landscapeSafeAreaInsets?.left || 0);
|
|
583
|
+
editor.control('landscape-safe-area-top').value = this.toNumericInputValue(landscapeSafeAreaInsets?.top || 0);
|
|
584
|
+
editor.control('landscape-safe-area-right').value = this.toNumericInputValue(landscapeSafeAreaInsets?.right || 0);
|
|
585
|
+
editor.control('landscape-safe-area-bottom').value = this.toNumericInputValue(landscapeSafeAreaInsets?.bottom || 0);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
private populateCutoutEditor(editor: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>,
|
|
589
|
+
device: EmulationModel.EmulatedDevices.EmulatedDevice): void {
|
|
590
|
+
const cutout = this.verticalMode(device)?.cutout;
|
|
591
|
+
editor.control('cutout-shape').value = cutout?.shape || NO_CUSTOM_CUTOUT;
|
|
592
|
+
editor.control('cutout-x').value = String(cutout?.x ?? '');
|
|
593
|
+
editor.control('cutout-y').value = String(cutout?.y ?? '');
|
|
594
|
+
editor.control('cutout-width').value = String(cutout?.width ?? '');
|
|
595
|
+
editor.control('cutout-height').value = String(cutout?.height ?? '');
|
|
596
|
+
editor.control('cutout-border-radius').value =
|
|
597
|
+
String(cutout?.shape === EmulationModel.EmulatedDevices.CutoutShape.PILL ? cutout.borderRadius : '');
|
|
598
|
+
editor.control('cutout-upper-radius').value =
|
|
599
|
+
String(cutout?.shape === EmulationModel.EmulatedDevices.CutoutShape.NOTCH ? cutout.upperRadius : '');
|
|
600
|
+
editor.control('cutout-lower-radius').value =
|
|
601
|
+
String(cutout?.shape === EmulationModel.EmulatedDevices.CutoutShape.NOTCH ? cutout.lowerRadius : '');
|
|
602
|
+
editor.control('cutout-cx').value =
|
|
603
|
+
String(cutout?.shape === EmulationModel.EmulatedDevices.CutoutShape.CIRCLE ? cutout.cx : '');
|
|
604
|
+
editor.control('cutout-cy').value =
|
|
605
|
+
String(cutout?.shape === EmulationModel.EmulatedDevices.CutoutShape.CIRCLE ? cutout.cy : '');
|
|
606
|
+
editor.control('cutout-radius').value =
|
|
607
|
+
String(cutout?.shape === EmulationModel.EmulatedDevices.CutoutShape.CIRCLE ? cutout.radius : '');
|
|
608
|
+
this.updateCutoutFieldsVisibility(editor);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
private updateCutoutFieldsVisibility(editor: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>):
|
|
612
|
+
void {
|
|
613
|
+
const shape = editor.control('cutout-shape').value;
|
|
614
|
+
const noCutout = shape === NO_CUSTOM_CUTOUT;
|
|
615
|
+
const isPill = shape === EmulationModel.EmulatedDevices.CutoutShape.PILL;
|
|
616
|
+
const isNotch = shape === EmulationModel.EmulatedDevices.CutoutShape.NOTCH;
|
|
617
|
+
const isCircle = shape === EmulationModel.EmulatedDevices.CutoutShape.CIRCLE;
|
|
618
|
+
const content = editor.contentElement();
|
|
619
|
+
const rectRow = content.querySelector<HTMLElement>('.devices-edit-cutout-rect-row');
|
|
620
|
+
const radiusRow = content.querySelector<HTMLElement>('.devices-edit-cutout-radius-row');
|
|
621
|
+
if (rectRow) {
|
|
622
|
+
rectRow.hidden = noCutout;
|
|
623
|
+
}
|
|
624
|
+
if (radiusRow) {
|
|
625
|
+
radiusRow.hidden = noCutout || !(isPill || isNotch || isCircle);
|
|
626
|
+
}
|
|
627
|
+
(editor.control('cutout-border-radius') as HTMLElement).hidden = !isPill;
|
|
628
|
+
(editor.control('cutout-upper-radius') as HTMLElement).hidden = !isNotch;
|
|
629
|
+
(editor.control('cutout-lower-radius') as HTMLElement).hidden = !isNotch;
|
|
630
|
+
(editor.control('cutout-cx') as HTMLElement).hidden = !isCircle;
|
|
631
|
+
(editor.control('cutout-cy') as HTMLElement).hidden = !isCircle;
|
|
632
|
+
(editor.control('cutout-radius') as HTMLElement).hidden = !isCircle;
|
|
633
|
+
}
|
|
634
|
+
|
|
295
635
|
private createEditor(): UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice> {
|
|
296
636
|
if (this.editor) {
|
|
297
637
|
return this.editor;
|
|
@@ -313,6 +653,24 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
313
653
|
dpr.classList.add('device-edit-fixed');
|
|
314
654
|
screen.appendChild(dpr);
|
|
315
655
|
|
|
656
|
+
this.appendSafeAreaFields(editor, deviceFields, i18nString(UIStrings.portraitSafeArea), '',
|
|
657
|
+
portraitSafeAreaValidator);
|
|
658
|
+
this.appendSafeAreaFields(editor, deviceFields, i18nString(UIStrings.landscapeSafeArea), 'landscape-',
|
|
659
|
+
landscapeSafeAreaValidator);
|
|
660
|
+
this.appendCutoutFields(editor, content, {
|
|
661
|
+
shape: cutoutShapeValidator,
|
|
662
|
+
x: cutoutXValidator,
|
|
663
|
+
y: cutoutYValidator,
|
|
664
|
+
width: cutoutWidthValidator,
|
|
665
|
+
height: cutoutHeightValidator,
|
|
666
|
+
pillRadius: cutoutPillRadiusValidator,
|
|
667
|
+
notchUpperRadius: cutoutNotchUpperRadiusValidator,
|
|
668
|
+
notchLowerRadius: cutoutNotchLowerRadiusValidator,
|
|
669
|
+
circleCenterX: cutoutCircleCenterXValidator,
|
|
670
|
+
circleCenterY: cutoutCircleCenterYValidator,
|
|
671
|
+
circleRadius: cutoutCircleRadiusValidator,
|
|
672
|
+
});
|
|
673
|
+
|
|
316
674
|
const uaStringFields = content.createChild('div', 'devices-edit-fields');
|
|
317
675
|
UI.UIUtils.createTextChild(uaStringFields.createChild('b'), i18nString(UIStrings.userAgentString));
|
|
318
676
|
|
|
@@ -389,5 +747,279 @@ export class DevicesSettingsTab extends UI.Widget.VBox implements
|
|
|
389
747
|
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
390
748
|
return EmulationModel.DeviceModeModel.DeviceModeModel.scaleValidator(input.value);
|
|
391
749
|
}
|
|
750
|
+
|
|
751
|
+
function nonNegativeIntegerValue(controlName: string): number|null {
|
|
752
|
+
return parseOptionalNonNegativeInteger(editor.control(controlName).value);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
function positiveIntegerValue(controlName: string): number|null {
|
|
756
|
+
const value = nonNegativeIntegerValue(controlName);
|
|
757
|
+
return value && value > 0 ? value : null;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
function requiredIntegerValue(controlName: string): number|null {
|
|
761
|
+
const value = editor.control(controlName).value.trim();
|
|
762
|
+
return value ? parseOptionalNonNegativeInteger(value) : null;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
function controlLabel(input: UI.ListWidget.EditorControl): string {
|
|
766
|
+
return input.getAttribute('aria-label') || input.getAttribute('placeholder') || '';
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
function safeAreaValidator(controlPrefix: string, orientationLabel: string, widthControlName: string,
|
|
770
|
+
heightControlName: string,
|
|
771
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
772
|
+
const ownValue = parseOptionalNonNegativeInteger(input.value);
|
|
773
|
+
if (ownValue === null) {
|
|
774
|
+
return {
|
|
775
|
+
valid: false,
|
|
776
|
+
errorMessage: i18nString(UIStrings.safeAreaValueMustBeInRange, {
|
|
777
|
+
PH1: orientationLabel,
|
|
778
|
+
PH2: input.getAttribute('aria-label') || input.getAttribute('placeholder') || '',
|
|
779
|
+
PH3: EmulationModel.DeviceModeModel.MaxDeviceSize,
|
|
780
|
+
}),
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
const left = nonNegativeIntegerValue(`${controlPrefix}safe-area-left`);
|
|
785
|
+
const top = nonNegativeIntegerValue(`${controlPrefix}safe-area-top`);
|
|
786
|
+
const right = nonNegativeIntegerValue(`${controlPrefix}safe-area-right`);
|
|
787
|
+
const bottom = nonNegativeIntegerValue(`${controlPrefix}safe-area-bottom`);
|
|
788
|
+
const width = positiveIntegerValue(widthControlName);
|
|
789
|
+
const height = positiveIntegerValue(heightControlName);
|
|
790
|
+
if (input === editor.control(`${controlPrefix}safe-area-right`) && left !== null && right !== null &&
|
|
791
|
+
width !== null && left + right > width) {
|
|
792
|
+
return {
|
|
793
|
+
valid: false,
|
|
794
|
+
errorMessage: i18nString(UIStrings.safeAreaHorizontalInsetsExceedWidth, {PH1: orientationLabel}),
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
if (input === editor.control(`${controlPrefix}safe-area-bottom`) && top !== null && bottom !== null &&
|
|
798
|
+
height !== null && top + bottom > height) {
|
|
799
|
+
return {
|
|
800
|
+
valid: false,
|
|
801
|
+
errorMessage: i18nString(UIStrings.safeAreaVerticalInsetsExceedHeight, {PH1: orientationLabel}),
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
return {valid: true};
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
function portraitSafeAreaValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
808
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
809
|
+
return safeAreaValidator('', i18nString(UIStrings.portraitSafeArea), 'width', 'height', input);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
function landscapeSafeAreaValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
813
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
814
|
+
return safeAreaValidator('landscape-', i18nString(UIStrings.landscapeSafeArea), 'height', 'width', input);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
function cutoutShapeValidator(): UI.ListWidget.ValidatorResult {
|
|
818
|
+
return {valid: true};
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
function cutoutValueValidator(input: UI.ListWidget.EditorControl,
|
|
822
|
+
mustBePositive = false): UI.ListWidget.ValidatorResult {
|
|
823
|
+
const label = controlLabel(input);
|
|
824
|
+
const value = input.value.trim();
|
|
825
|
+
if (!value) {
|
|
826
|
+
return {valid: false, errorMessage: i18nString(UIStrings.cutoutFieldRequired, {PH1: label})};
|
|
827
|
+
}
|
|
828
|
+
const numericValue = parseOptionalNonNegativeInteger(value);
|
|
829
|
+
if (numericValue === null) {
|
|
830
|
+
return {
|
|
831
|
+
valid: false,
|
|
832
|
+
errorMessage: i18nString(UIStrings.cutoutValueMustBeInRange, {
|
|
833
|
+
PH1: label,
|
|
834
|
+
PH2: EmulationModel.DeviceModeModel.MaxDeviceSize,
|
|
835
|
+
}),
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
if (mustBePositive && numericValue === 0) {
|
|
839
|
+
return {valid: false, errorMessage: i18nString(UIStrings.cutoutValueMustBePositiveInteger, {PH1: label})};
|
|
840
|
+
}
|
|
841
|
+
return {valid: true};
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
function isCutoutFieldActive(shape?: EmulationModel.EmulatedDevices.CutoutShape): boolean {
|
|
845
|
+
const selectedShape = editor.control('cutout-shape').value;
|
|
846
|
+
return selectedShape !== NO_CUSTOM_CUTOUT && (shape === undefined || selectedShape === shape);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
function cutoutXValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
850
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
851
|
+
return isCutoutFieldActive() ? cutoutValueValidator(input) : {valid: true};
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
function cutoutYValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
855
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
856
|
+
return isCutoutFieldActive() ? cutoutValueValidator(input) : {valid: true};
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
function cutoutWidthValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
860
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
861
|
+
if (!isCutoutFieldActive()) {
|
|
862
|
+
return {valid: true};
|
|
863
|
+
}
|
|
864
|
+
const validation = cutoutValueValidator(input, true);
|
|
865
|
+
if (!validation.valid) {
|
|
866
|
+
return validation;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
const cutoutX = requiredIntegerValue('cutout-x');
|
|
870
|
+
const cutoutWidth = positiveIntegerValue('cutout-width');
|
|
871
|
+
const width = positiveIntegerValue('width');
|
|
872
|
+
if (width !== null && cutoutX !== null && cutoutWidth !== null && cutoutX + cutoutWidth > width) {
|
|
873
|
+
return {valid: false, errorMessage: i18nString(UIStrings.cutoutXAndWidthExceedDeviceWidth)};
|
|
874
|
+
}
|
|
875
|
+
return {valid: true};
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
function cutoutHeightValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
879
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
880
|
+
if (!isCutoutFieldActive()) {
|
|
881
|
+
return {valid: true};
|
|
882
|
+
}
|
|
883
|
+
const validation = cutoutValueValidator(input, true);
|
|
884
|
+
if (!validation.valid) {
|
|
885
|
+
return validation;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
const cutoutY = requiredIntegerValue('cutout-y');
|
|
889
|
+
const cutoutHeight = positiveIntegerValue('cutout-height');
|
|
890
|
+
const height = positiveIntegerValue('height');
|
|
891
|
+
if (height !== null && cutoutY !== null && cutoutHeight !== null && cutoutY + cutoutHeight > height) {
|
|
892
|
+
return {valid: false, errorMessage: i18nString(UIStrings.cutoutYAndHeightExceedDeviceHeight)};
|
|
893
|
+
}
|
|
894
|
+
return {valid: true};
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
function cutoutPillRadiusValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
898
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
899
|
+
return isCutoutFieldActive(EmulationModel.EmulatedDevices.CutoutShape.PILL) ? cutoutValueValidator(input) :
|
|
900
|
+
{valid: true};
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
function cutoutNotchUpperRadiusValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
904
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
905
|
+
return isCutoutFieldActive(EmulationModel.EmulatedDevices.CutoutShape.NOTCH) ? cutoutValueValidator(input) :
|
|
906
|
+
{valid: true};
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
function cutoutNotchLowerRadiusValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
910
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
911
|
+
return isCutoutFieldActive(EmulationModel.EmulatedDevices.CutoutShape.NOTCH) ? cutoutValueValidator(input) :
|
|
912
|
+
{valid: true};
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
function cutoutCircleCenterXValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
916
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
917
|
+
return isCutoutFieldActive(EmulationModel.EmulatedDevices.CutoutShape.CIRCLE) ? cutoutValueValidator(input) :
|
|
918
|
+
{valid: true};
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
function cutoutCircleCenterYValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
922
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
923
|
+
return isCutoutFieldActive(EmulationModel.EmulatedDevices.CutoutShape.CIRCLE) ? cutoutValueValidator(input) :
|
|
924
|
+
{valid: true};
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
function cutoutCircleRadiusValidator(_item: EmulationModel.EmulatedDevices.EmulatedDevice, _index: number,
|
|
928
|
+
input: UI.ListWidget.EditorControl): UI.ListWidget.ValidatorResult {
|
|
929
|
+
if (!isCutoutFieldActive(EmulationModel.EmulatedDevices.CutoutShape.CIRCLE)) {
|
|
930
|
+
return {valid: true};
|
|
931
|
+
}
|
|
932
|
+
const validation = cutoutValueValidator(input, true);
|
|
933
|
+
if (!validation.valid) {
|
|
934
|
+
return validation;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
const cutoutX = requiredIntegerValue('cutout-x');
|
|
938
|
+
const cutoutY = requiredIntegerValue('cutout-y');
|
|
939
|
+
const cutoutWidth = positiveIntegerValue('cutout-width');
|
|
940
|
+
const cutoutHeight = positiveIntegerValue('cutout-height');
|
|
941
|
+
const centerX = requiredIntegerValue('cutout-cx');
|
|
942
|
+
const centerY = requiredIntegerValue('cutout-cy');
|
|
943
|
+
const radius = positiveIntegerValue('cutout-radius');
|
|
944
|
+
if (cutoutX !== null && cutoutY !== null && cutoutWidth !== null && cutoutHeight !== null && centerX !== null &&
|
|
945
|
+
centerY !== null && radius !== null &&
|
|
946
|
+
(centerX - radius < cutoutX || centerX + radius > cutoutX + cutoutWidth || centerY - radius < cutoutY ||
|
|
947
|
+
centerY + radius > cutoutY + cutoutHeight)) {
|
|
948
|
+
return {valid: false, errorMessage: i18nString(UIStrings.circleMustFitCutoutBounds)};
|
|
949
|
+
}
|
|
950
|
+
return {valid: true};
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
private appendSafeAreaFields(editor: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>,
|
|
955
|
+
deviceFields: HTMLElement, title: string, controlPrefix: string,
|
|
956
|
+
safeAreaValidator:
|
|
957
|
+
(item: EmulationModel.EmulatedDevices.EmulatedDevice, index: number,
|
|
958
|
+
input: UI.ListWidget.EditorControl) => UI.ListWidget.ValidatorResult): void {
|
|
959
|
+
const safeAreaGroup = deviceFields.createChild('div', 'devices-edit-safe-area-group');
|
|
960
|
+
UI.ARIAUtils.markAsGroup(safeAreaGroup);
|
|
961
|
+
const heading = safeAreaGroup.createChild('b');
|
|
962
|
+
heading.id = UI.ARIAUtils.nextId('safe-area-heading-');
|
|
963
|
+
UI.UIUtils.createTextChild(heading, title);
|
|
964
|
+
safeAreaGroup.setAttribute('aria-labelledby', heading.id);
|
|
965
|
+
const safeAreaRow = safeAreaGroup.createChild('div', 'hbox');
|
|
966
|
+
safeAreaRow.appendChild(editor.createInput(`${controlPrefix}safe-area-left`, 'text',
|
|
967
|
+
i18nString(UIStrings.safeAreaLeft), safeAreaValidator));
|
|
968
|
+
safeAreaRow.appendChild(editor.createInput(`${controlPrefix}safe-area-top`, 'text',
|
|
969
|
+
i18nString(UIStrings.safeAreaTop), safeAreaValidator));
|
|
970
|
+
safeAreaRow.appendChild(editor.createInput(`${controlPrefix}safe-area-right`, 'text',
|
|
971
|
+
i18nString(UIStrings.safeAreaRight), safeAreaValidator));
|
|
972
|
+
safeAreaRow.appendChild(editor.createInput(`${controlPrefix}safe-area-bottom`, 'text',
|
|
973
|
+
i18nString(UIStrings.safeAreaBottom), safeAreaValidator));
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
private appendCutoutFields(editor: UI.ListWidget.Editor<EmulationModel.EmulatedDevices.EmulatedDevice>,
|
|
977
|
+
content: Element, validators: CutoutFieldValidators): void {
|
|
978
|
+
const cutoutFields = content.createChild('div', 'devices-edit-fields');
|
|
979
|
+
cutoutFields.classList.add('devices-edit-cutout-fields');
|
|
980
|
+
UI.ARIAUtils.markAsGroup(cutoutFields);
|
|
981
|
+
const heading = cutoutFields.createChild('b');
|
|
982
|
+
heading.id = UI.ARIAUtils.nextId('cutout-heading-');
|
|
983
|
+
UI.UIUtils.createTextChild(heading, i18nString(UIStrings.displayCutout));
|
|
984
|
+
cutoutFields.setAttribute('aria-labelledby', heading.id);
|
|
985
|
+
const shapeOptions = [
|
|
986
|
+
NO_CUSTOM_CUTOUT,
|
|
987
|
+
EmulationModel.EmulatedDevices.CutoutShape.PILL,
|
|
988
|
+
EmulationModel.EmulatedDevices.CutoutShape.NOTCH,
|
|
989
|
+
EmulationModel.EmulatedDevices.CutoutShape.CIRCLE,
|
|
990
|
+
EmulationModel.EmulatedDevices.CutoutShape.RECTANGLE,
|
|
991
|
+
];
|
|
992
|
+
const shapeControl =
|
|
993
|
+
editor.createSelect('cutout-shape', shapeOptions, validators.shape, i18nString(UIStrings.displayCutout));
|
|
994
|
+
shapeControl.options[0].textContent = i18nString(UIStrings.noDisplayCutout);
|
|
995
|
+
shapeControl.options[1].textContent = i18nString(UIStrings.pillDisplayCutout);
|
|
996
|
+
shapeControl.options[2].textContent = i18nString(UIStrings.notchDisplayCutout);
|
|
997
|
+
shapeControl.options[3].textContent = i18nString(UIStrings.circleDisplayCutout);
|
|
998
|
+
shapeControl.options[4].textContent = i18nString(UIStrings.rectangleDisplayCutout);
|
|
999
|
+
cutoutFields.createChild('div', 'hbox').appendChild(shapeControl);
|
|
1000
|
+
shapeControl.addEventListener('input', () => this.updateCutoutFieldsVisibility(editor), false);
|
|
1001
|
+
|
|
1002
|
+
const rectRow = cutoutFields.createChild('div', 'hbox devices-edit-cutout-rect-row');
|
|
1003
|
+
rectRow.appendChild(editor.createInput('cutout-x', 'text', i18nString(UIStrings.cutoutX), validators.x));
|
|
1004
|
+
rectRow.appendChild(editor.createInput('cutout-y', 'text', i18nString(UIStrings.cutoutY), validators.y));
|
|
1005
|
+
rectRow.appendChild(
|
|
1006
|
+
editor.createInput('cutout-width', 'text', i18nString(UIStrings.cutoutWidth), validators.width));
|
|
1007
|
+
rectRow.appendChild(
|
|
1008
|
+
editor.createInput('cutout-height', 'text', i18nString(UIStrings.cutoutHeight), validators.height));
|
|
1009
|
+
|
|
1010
|
+
const radiusRow = cutoutFields.createChild('div', 'hbox devices-edit-cutout-radius-row');
|
|
1011
|
+
radiusRow.appendChild(editor.createInput('cutout-border-radius', 'text', i18nString(UIStrings.cutoutBorderRadius),
|
|
1012
|
+
validators.pillRadius));
|
|
1013
|
+
radiusRow.appendChild(editor.createInput('cutout-upper-radius', 'text', i18nString(UIStrings.cutoutUpperRadius),
|
|
1014
|
+
validators.notchUpperRadius));
|
|
1015
|
+
radiusRow.appendChild(editor.createInput('cutout-lower-radius', 'text', i18nString(UIStrings.cutoutLowerRadius),
|
|
1016
|
+
validators.notchLowerRadius));
|
|
1017
|
+
radiusRow.appendChild(
|
|
1018
|
+
editor.createInput('cutout-cx', 'text', i18nString(UIStrings.cutoutCenterX), validators.circleCenterX));
|
|
1019
|
+
radiusRow.appendChild(
|
|
1020
|
+
editor.createInput('cutout-cy', 'text', i18nString(UIStrings.cutoutCenterY), validators.circleCenterY));
|
|
1021
|
+
radiusRow.appendChild(
|
|
1022
|
+
editor.createInput('cutout-radius', 'text', i18nString(UIStrings.cutoutRadius), validators.circleRadius));
|
|
1023
|
+
this.updateCutoutFieldsVisibility(editor);
|
|
392
1024
|
}
|
|
393
1025
|
}
|