diff --git a/resources/Images/cross.svg b/resources/Images/cross.svg new file mode 100644 index 00000000..ac8b85c0 --- /dev/null +++ b/resources/Images/cross.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/Images/info-icon.svg b/resources/Images/info-icon.svg new file mode 100644 index 00000000..5857d850 --- /dev/null +++ b/resources/Images/info-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 79837f68..088513a2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -179,6 +179,14 @@ export function activate(context: vscode.ExtensionContext): void { const normalizedPath = new URL(target.description).toString(); if (browserInstance) { const browserPages = await browserInstance.pages(); + + // First we validate we have pages to close, some non-visual targets could keep the browser + // instance alive. + if (!browserPages || browserPages.length === 0){ + void browserInstance.close(); + return; + } + for (const page of browserPages) { // URL needs to be accessed through the target as the page could be handling errors in a different way. // e.g redirecting to chrome-error: protocol diff --git a/src/screencast/infobar.ts b/src/screencast/infobar.ts new file mode 100644 index 00000000..36c474b5 --- /dev/null +++ b/src/screencast/infobar.ts @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { html, render } from 'lit-html'; +import { createRef, ref } from 'lit-html/directives/ref.js' +import { styleMap, StyleInfo } from 'lit-html/directives/style-map.js'; + +interface InfobarProps { + message: string; +} + +export default class InfobarComponent { + #buttonRef = createRef(); + #message: string; + #container: HTMLElement | undefined; + + constructor(props: InfobarProps, container?: HTMLElement) { + this.#message = props.message; + this.#container = container; + this.#update(); + } + + #update(styles?: StyleInfo) { + let customStyles = styles ?? { + display: 'flex' + }; + + if (!this.#container) { + return; + } + render(this.template(customStyles), this.#container); + } + + template(styles: StyleInfo) { + return html` +
+ `; + } + + #onClick = () => { + let styles = { + display: 'none', + } as StyleInfo; + + this.#update(styles); + }; + + static render(props: InfobarProps, elementId: string) { + const currentContainer = document.getElementById(elementId); + if (currentContainer) { + new InfobarComponent(props, currentContainer); + } + } +} diff --git a/src/screencast/screencast.ts b/src/screencast/screencast.ts index d41e3805..a5802a66 100644 --- a/src/screencast/screencast.ts +++ b/src/screencast/screencast.ts @@ -8,6 +8,7 @@ import { MouseEventMap, ScreencastInputHandler } from './input'; import DimensionComponent from './dimensionComponent'; import { getEmulatedDeviceDetails, groupEmulatedDevicesByType } from './emulatedDeviceHelpers'; import FlyoutMenuComponent, {OffsetDirection} from './flyoutMenuComponent'; +import InfobarComponent from './infobar'; import { encodeMessageForChannel } from '../common/webviewEvents'; @@ -58,7 +59,7 @@ export class Screencast { this.urlInput.addEventListener('keydown', event => this.onUrlKeyDown(event)); const emulatedDevices = groupEmulatedDevicesByType(); - + InfobarComponent.render({message: "This is a simulated preview with limited functionality. Deactivate 'Headless mode' in extension settings for a full experience."}, 'infobar'); FlyoutMenuComponent.render({ iconName: 'codicon-chevron-down', title: 'Emulate devices', diff --git a/src/screencast/view.css b/src/screencast/view.css index 2b113466..b078fd24 100644 --- a/src/screencast/view.css +++ b/src/screencast/view.css @@ -198,3 +198,31 @@ body { .devtools-open { color: #7dbae9; } + +.infobar { + flex-direction: row; + width: 100vw; + color: black; + background-color: rgb(254 246 213 / 100%); + height: 30px; +} + +.infobar-message { + text-align: left; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-size: small; + padding: 5px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.infobar-close-button { + background-image: url('../../resources/Images/cross.svg'); + background-repeat: no-repeat; + align-self: right; + background-size: 18px; + width: 20px; + height: 20px; + margin: 5px 10px 5px auto; +} diff --git a/src/screencast/view.ts b/src/screencast/view.ts index d3873d5f..1c89984f 100644 --- a/src/screencast/view.ts +++ b/src/screencast/view.ts @@ -29,6 +29,7 @@ export class ScreencastView {