@cmusei/console-forge 0.19.0 → 0.20.0

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.
@@ -174,7 +174,8 @@ class UserSettingsService {
174
174
  _settings = signal({
175
175
  console: {
176
176
  allowCopyToLocalClipboard: true,
177
- preserveAspectRatioOnScale: true
177
+ attemptRemoteSessionResize: true,
178
+ scaleToCanvasHostSize: true,
178
179
  },
179
180
  toolbar: {
180
181
  dockTo: "left",
@@ -323,7 +324,7 @@ class ConsoleToolbarDefaultComponent {
323
324
  isPowerDialogOpen = false;
324
325
  isSettingsDialogOpen = false;
325
326
  keyboardInputText = model("");
326
- selectedNetworkForChange = model();
327
+ // protected readonly selected = model<string>();
327
328
  // services and viewkids
328
329
  cfConfig = inject(ConsoleForgeConfig);
329
330
  clipboardService = inject(ClipboardService);
@@ -333,12 +334,12 @@ class ConsoleToolbarDefaultComponent {
333
334
  // trying this out. when the network configuration (which is passed into the library by the end dev)
334
335
  // changes, we need to update the model that holds the current network, so let's make a computed
335
336
  // signal that represents that change so we can be sure our effect only happens when we want it to
336
- currentNetwork = (() => this.consoleContext()?.networks?.config()?.current || "");
337
+ // private readonly currentNetwork = (() => this.consoleContext()?.networks?.config()?.current || "");
337
338
  constructor() {
338
339
  // when the network config is changed, select the current network if exists
339
- effect(() => {
340
- this.selectedNetworkForChange.update(() => this.currentNetwork());
341
- });
340
+ // effect(() => {
341
+ // this.selectedNetworkForChange.update(() => this.currentNetwork());
342
+ // });
342
343
  }
343
344
  async ngAfterViewInit() {
344
345
  // apply pico to this component
@@ -360,16 +361,19 @@ class ConsoleToolbarDefaultComponent {
360
361
  handleClipboardCopyLastText(text) {
361
362
  this.clipboardService.copyText(text);
362
363
  }
363
- handleNetworkChangeRequested(networkName) {
364
- console.log("changed", networkName);
365
- if (!networkName) {
366
- this.consoleContext().networks.disconnectRequested();
364
+ handleNetworkChangeRequested(request) {
365
+ if (!request.network) {
366
+ this.consoleContext().networks.disconnectRequested({ nic: request.nic });
367
367
  }
368
368
  else {
369
- this.consoleContext().networks.connectionRequested(networkName);
369
+ this.consoleContext().networks.connectionRequested(request);
370
370
  }
371
371
  this.isNetworkDialogOpen = false;
372
372
  }
373
+ handleNetworkDisconnectAllRequested() {
374
+ this.consoleContext().networks.disconnectRequested({});
375
+ this.isNetworkDialogOpen = false;
376
+ }
373
377
  handleNetworkDialogOpenClose(isOpen) {
374
378
  this.isNetworkDialogOpen = isOpen;
375
379
  }
@@ -411,14 +415,17 @@ class ConsoleToolbarDefaultComponent {
411
415
  handleSettingsAllowLocalClipboardWrite(allow) {
412
416
  this.consoleContext().userSettings.patch({ console: { allowCopyToLocalClipboard: allow } });
413
417
  }
414
- handleSettingsPreserveAspectRatioChange(preserveAspectRatioOnScale) {
415
- this.consoleContext().userSettings.patch({ console: { preserveAspectRatioOnScale } });
418
+ handleSettingsAttemptRemoteSessionResize(attempt) {
419
+ this.consoleContext().userSettings.patch({ console: { attemptRemoteSessionResize: attempt } });
420
+ }
421
+ handleSettingsScaleToContainerHostSize(scaleToCanvasHostSize) {
422
+ this.consoleContext().userSettings.patch({ console: { scaleToCanvasHostSize } });
416
423
  }
417
424
  handleToolbarThemeChange(theme) {
418
425
  this.consoleContext().userSettings.patch({ toolbar: { preferTheme: theme } });
419
426
  }
420
427
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
421
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleToolbarDefaultComponent, isStandalone: true, selector: "cf-console-toolbar-default", inputs: { consoleContext: { classPropertyName: "consoleContext", publicName: "consoleContext", isSignal: true, isRequired: true, transformFunction: null }, keyboardInputText: { classPropertyName: "keyboardInputText", publicName: "keyboardInputText", isSignal: true, isRequired: false, transformFunction: null }, selectedNetworkForChange: { classPropertyName: "selectedNetworkForChange", publicName: "selectedNetworkForChange", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { keyboardInputText: "keyboardInputTextChange", selectedNetworkForChange: "selectedNetworkForChangeChange" }, viewQueries: [{ propertyName: "clipboardTextInput", first: true, predicate: ["clipboardText"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\" cfApplyToolbarTheme\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12.0002 8C9.79111 8 8.00024 9.79086 8.00024 12C8.00024 14.2091 9.79111 16 12.0002 16C14.2094 16 16.0002 14.2091 16.0002 12C16.0002 9.79086 14.2094 8 12.0002 8ZM10.0002 12C10.0002 10.8954 10.8957 10 12.0002 10C13.1048 10 14.0002 10.8954 14.0002 12C14.0002 13.1046 13.1048 14 12.0002 14C10.8957 14 10.0002 13.1046 10.0002 12Z\"\n fill=\"#000000\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.2867 0.5C9.88583 0.5 8.6461 1.46745 8.37171 2.85605L8.29264 3.25622C8.10489 4.20638 7.06195 4.83059 6.04511 4.48813L5.64825 4.35447C4.32246 3.90796 2.83873 4.42968 2.11836 5.63933L1.40492 6.83735C0.67773 8.05846 0.954349 9.60487 2.03927 10.5142L2.35714 10.7806C3.12939 11.4279 3.12939 12.5721 2.35714 13.2194L2.03927 13.4858C0.954349 14.3951 0.67773 15.9415 1.40492 17.1626L2.11833 18.3606C2.83872 19.5703 4.3225 20.092 5.64831 19.6455L6.04506 19.5118C7.06191 19.1693 8.1049 19.7935 8.29264 20.7437L8.37172 21.1439C8.6461 22.5325 9.88584 23.5 11.2867 23.5H12.7136C14.1146 23.5 15.3543 22.5325 15.6287 21.1438L15.7077 20.7438C15.8954 19.7936 16.9384 19.1693 17.9553 19.5118L18.3521 19.6455C19.6779 20.092 21.1617 19.5703 21.8821 18.3606L22.5955 17.1627C23.3227 15.9416 23.046 14.3951 21.9611 13.4858L21.6432 13.2194C20.8709 12.5722 20.8709 11.4278 21.6432 10.7806L21.9611 10.5142C23.046 9.60489 23.3227 8.05845 22.5955 6.83732L21.8821 5.63932C21.1617 4.42968 19.678 3.90795 18.3522 4.35444L17.9552 4.48814C16.9384 4.83059 15.8954 4.20634 15.7077 3.25617L15.6287 2.85616C15.3543 1.46751 14.1146 0.5 12.7136 0.5H11.2867ZM10.3338 3.24375C10.4149 2.83334 10.7983 2.5 11.2867 2.5H12.7136C13.2021 2.5 13.5855 2.83336 13.6666 3.24378L13.7456 3.64379C14.1791 5.83811 16.4909 7.09167 18.5935 6.38353L18.9905 6.24984C19.4495 6.09527 19.9394 6.28595 20.1637 6.66264L20.8771 7.86064C21.0946 8.22587 21.0208 8.69271 20.6764 8.98135L20.3586 9.24773C18.6325 10.6943 18.6325 13.3057 20.3586 14.7523L20.6764 15.0186C21.0208 15.3073 21.0946 15.7741 20.8771 16.1394L20.1637 17.3373C19.9394 17.714 19.4495 17.9047 18.9905 17.7501L18.5936 17.6164C16.4909 16.9082 14.1791 18.1618 13.7456 20.3562L13.6666 20.7562C13.5855 21.1666 13.2021 21.5 12.7136 21.5H11.2867C10.7983 21.5 10.4149 21.1667 10.3338 20.7562L10.2547 20.356C9.82113 18.1617 7.50931 16.9082 5.40665 17.6165L5.0099 17.7501C4.55092 17.9047 4.06104 17.714 3.83671 17.3373L3.1233 16.1393C2.9058 15.7741 2.97959 15.3073 3.32398 15.0186L3.64185 14.7522C5.36782 13.3056 5.36781 10.6944 3.64185 9.24779L3.32398 8.98137C2.97959 8.69273 2.9058 8.2259 3.1233 7.86067L3.83674 6.66266C4.06106 6.28596 4.55093 6.09528 5.0099 6.24986L5.40676 6.38352C7.50938 7.09166 9.82112 5.83819 10.2547 3.64392L10.3338 3.24375Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(consoleContext().state.isManualReconnectAvailable())\n {\n <cf-console-toolbar-default-button label=\"Reconnect\"\n (clicked)=\"consoleContext().console.sendReconnectRequest()\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C16.3556 22 20.0584 19.2159 21.4307 15.3332C21.6148 14.8125 21.3418 14.2412 20.8211 14.0572C20.3004 13.8731 19.7291 14.146 19.545 14.6668C18.4463 17.7753 15.4817 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C13.5516 4 14.8662 4.56117 16.1162 5.4406C16.9569 6.03212 17.7348 6.74106 18.5242 7.5H15.5C14.9477 7.5 14.5 7.94772 14.5 8.5C14.5 9.05228 14.9477 9.5 15.5 9.5H21C21.5523 9.5 22 9.05228 22 8.5V3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3V6.14371C19.1517 5.32583 18.2456 4.49337 17.267 3.80489C15.7949 2.76916 14.0847 2 12 2Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (!consoleContext().state.isViewOnly() && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Keyboard\" (clicked)=\"isKeyboardDialogOpen = true\">\n <svg fill=\"#000000\" viewBox=\"0 0 1920 1920\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M1807.059 1637.706c0 31.059-25.299 56.47-56.47 56.47H169.411c-31.172 0-56.47-25.411-56.47-56.47v-903.53c0-31.058 25.298-56.47 56.47-56.47h1581.176c31.172 0 56.47 25.412 56.47 56.47v903.53Zm-56.47-1072.941h-729.262c14.908-86.965 65.958-113.506 133.384-147.163 89.336-44.611 200.583-100.291 200.583-304.602h-112.941c0 134.513-57.939 163.426-138.24 203.633-80.301 40.094-177.544 90.24-196.518 248.132H169.412C76.009 564.765 0 640.775 0 734.176v903.53c0 93.402 76.01 169.412 169.412 169.412h1581.176c93.403 0 169.412-76.01 169.412-169.412v-903.53c0-93.402-76.01-169.411-169.412-169.411Zm-564.707 677.647H734.118c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h451.764c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.299 56.471-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m-1016.47 0H395.293c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m0-338.824h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m225.883 225.882h112.94c31.173 0 56.471-25.3 56.471-56.471V960.059c0-31.172-25.298-56.47-56.47-56.47h-112.94c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47m451.764-225.882h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.298 56.471-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47\"\n fill-rule=\"evenodd\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(!cfConfig.disabledFeatures.clipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" preserveAspectRatio=\"none\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19.5 16.5L19.5 4.5L18.75 3.75H9L8.25 4.5L8.25 7.5L5.25 7.5L4.5 8.25V20.25L5.25 21H15L15.75 20.25V17.25H18.75L19.5 16.5ZM15.75 15.75L15.75 8.25L15 7.5L9.75 7.5V5.25L18 5.25V15.75H15.75ZM6 9L14.25 9L14.25 19.5L6 19.5L6 9Z\"\n fill=\"#080341\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().networks.config()?.available?.length) {\n <cf-console-toolbar-default-button\n label=\"Networks ({{ consoleContext().networks.config()?.available?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button> }\n }\n\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (!cfConfig.disabledFeatures.consoleScreenRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <title>record [#979]</title>\n <desc>Created with Sketch.</desc>\n <defs> </defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M4 2C2.89543 2 2 2.89543 2 4V8C2 8.55228 2.44772 9 3 9C3.55228 9 4 8.55228 4 8V4H8C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2H4Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 2C21.1046 2 22 2.89543 22 4V8C22 8.55228 21.5523 9 21 9C20.4477 9 20 8.55228 20 8V4H16C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 22C21.1046 22 22 21.1046 22 20V16C22 15.4477 21.5523 15 21 15C20.4477 15 20 15.4477 20 16V20H16C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M2 20C2 21.1046 2.89543 22 4 22H8C8.55228 22 9 21.5523 9 21C9 20.4477 8.55228 20 8 20H4V16C4 15.4477 3.55228 15 3 15C2.44772 15 2 15.4477 2 16V20Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n </div>\n\n <dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Clipboard</strong>\n </p>\n </header>\n\n @if (consoleContext().console.supportedFeatures().clipboardRemoteWrite) {\n <div class=\"dialog-section\">\n <h2>Send Text to Console Clipboard</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n }\n\n @if(!consoleContext().userSettings.settings().console.allowCopyToLocalClipboard ||\n !consoleContext().console.supportedFeatures().clipboardAutomaticLocalCopy) {\n <div class=\"dialog-section\">\n <h2>Console Clipboard Content</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\" disabled\n [value]=\"consoleContext().clipboard.consoleClipboardText()\"\n placeholder=\"The console's clipboard content will appear here\" #consoleLastClipboardText>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n </form>\n </div>\n }\n </article>\n </dialog>\n\n <dialog [open]=\"isKeyboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isKeyboardDialogOpen = false\"></button>\n <p>\n <strong>Send Keystrokes</strong>\n </p>\n </header>\n\n <div class=\"dialog-section\">\n <h2>Send Keystrokes to Console</h2>\n <form (submit)=\"handleSendKeyboardInput($event, keyboardInputText())\">\n <fieldset role=\"group\">\n <input type=\"text\" name=\"keyboardInputText\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send as keyboard input to the console\" autofocus\n [(ngModel)]=\"keyboardInputText\">\n <button type=\"submit\"\n [disabled]=\"!keyboardInputText() || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n <div class=\"dialog-section\">\n <h2>Special Key Combinations</h2>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" aria-label=\"Send Ctrl+Alt+Delete\" (click)=\"handlSendKeyboardCtrlAltDel()\">\n Ctrl + Alt + Delete\n </button>\n </div>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Networks</strong>\n </p>\n </header>\n\n <form>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"current-network\" aria-label=\"Select a network to connect to\"\n [(ngModel)]=\"selectedNetworkForChange\" required>\n <option selected value=\"\">\n [Disconnect from network]\n </option>\n\n @for(network of consoleContext().networks.config()?.available; track network) {\n <option [value]=\"network\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\" (click)=\"handleNetworkChangeRequested(selectedNetworkForChange())\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n </form>\n </article>\n </dialog>\n\n <dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Power</strong>\n </p>\n </header>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.preserveAspectRatioOnScale\"\n (change)=\"handleSettingsPreserveAspectRatioChange(inputScaleToContainerSize.checked)\" />\n Preserve console aspect ratio when scaling size\n </label>\n </fieldset>\n\n <div class=\"settings-toolbar-dock\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <!-- see https://github.com/cmu-sei/console-forge/issues/12 -->\n <!-- <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button> -->\n </div>\n </div>\n\n <div class=\"settings-theme\">\n <h4>Theme</h4>\n <div role=\"group\">\n <button (click)=\"handleToolbarThemeChange('light')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'light'\">Light</button>\n <button (click)=\"handleToolbarThemeChange('dark')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'dark'\">Dark</button>\n <button (click)=\"handleToolbarThemeChange(undefined)\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === undefined\">\n My Default\n </button>\n </div>\n </div>\n </div>\n </article>\n </dialog>\n</div>\n}\n", styles: [":host{display:block;height:100%;width:100%;max-width:100%}fieldset legend{font-weight:700}.toolbar-container{background-color:var(--pico-background-color);padding:4px;height:100%;display:flex;align-items:center;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-color);margin:.25rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{align-self:stretch;border-left:1px solid var(--pico-color);height:auto;margin:0 1rem;width:1px}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.settings-toolbar-dock{margin-top:1rem}dialog h2{font-size:1.1rem;font-weight:700}dialog .dialog-section:not(:last-of-type){margin-bottom:1.5rem}dialog .dialog-button-group button{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: ApplyToolbarThemeDirective, selector: "[cfApplyToolbarTheme]" }, { kind: "component", type: ConsoleToolbarDefaultButtonComponent, selector: "cf-console-toolbar-default-button", inputs: ["disabled", "label", "isOngoing"], outputs: ["clicked"] }], encapsulation: i0.ViewEncapsulation.ShadowDom });
428
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleToolbarDefaultComponent, isStandalone: true, selector: "cf-console-toolbar-default", inputs: { consoleContext: { classPropertyName: "consoleContext", publicName: "consoleContext", isSignal: true, isRequired: true, transformFunction: null }, keyboardInputText: { classPropertyName: "keyboardInputText", publicName: "keyboardInputText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { keyboardInputText: "keyboardInputTextChange" }, viewQueries: [{ propertyName: "clipboardTextInput", first: true, predicate: ["clipboardText"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\" cfApplyToolbarTheme\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12.0002 8C9.79111 8 8.00024 9.79086 8.00024 12C8.00024 14.2091 9.79111 16 12.0002 16C14.2094 16 16.0002 14.2091 16.0002 12C16.0002 9.79086 14.2094 8 12.0002 8ZM10.0002 12C10.0002 10.8954 10.8957 10 12.0002 10C13.1048 10 14.0002 10.8954 14.0002 12C14.0002 13.1046 13.1048 14 12.0002 14C10.8957 14 10.0002 13.1046 10.0002 12Z\"\n fill=\"#000000\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.2867 0.5C9.88583 0.5 8.6461 1.46745 8.37171 2.85605L8.29264 3.25622C8.10489 4.20638 7.06195 4.83059 6.04511 4.48813L5.64825 4.35447C4.32246 3.90796 2.83873 4.42968 2.11836 5.63933L1.40492 6.83735C0.67773 8.05846 0.954349 9.60487 2.03927 10.5142L2.35714 10.7806C3.12939 11.4279 3.12939 12.5721 2.35714 13.2194L2.03927 13.4858C0.954349 14.3951 0.67773 15.9415 1.40492 17.1626L2.11833 18.3606C2.83872 19.5703 4.3225 20.092 5.64831 19.6455L6.04506 19.5118C7.06191 19.1693 8.1049 19.7935 8.29264 20.7437L8.37172 21.1439C8.6461 22.5325 9.88584 23.5 11.2867 23.5H12.7136C14.1146 23.5 15.3543 22.5325 15.6287 21.1438L15.7077 20.7438C15.8954 19.7936 16.9384 19.1693 17.9553 19.5118L18.3521 19.6455C19.6779 20.092 21.1617 19.5703 21.8821 18.3606L22.5955 17.1627C23.3227 15.9416 23.046 14.3951 21.9611 13.4858L21.6432 13.2194C20.8709 12.5722 20.8709 11.4278 21.6432 10.7806L21.9611 10.5142C23.046 9.60489 23.3227 8.05845 22.5955 6.83732L21.8821 5.63932C21.1617 4.42968 19.678 3.90795 18.3522 4.35444L17.9552 4.48814C16.9384 4.83059 15.8954 4.20634 15.7077 3.25617L15.6287 2.85616C15.3543 1.46751 14.1146 0.5 12.7136 0.5H11.2867ZM10.3338 3.24375C10.4149 2.83334 10.7983 2.5 11.2867 2.5H12.7136C13.2021 2.5 13.5855 2.83336 13.6666 3.24378L13.7456 3.64379C14.1791 5.83811 16.4909 7.09167 18.5935 6.38353L18.9905 6.24984C19.4495 6.09527 19.9394 6.28595 20.1637 6.66264L20.8771 7.86064C21.0946 8.22587 21.0208 8.69271 20.6764 8.98135L20.3586 9.24773C18.6325 10.6943 18.6325 13.3057 20.3586 14.7523L20.6764 15.0186C21.0208 15.3073 21.0946 15.7741 20.8771 16.1394L20.1637 17.3373C19.9394 17.714 19.4495 17.9047 18.9905 17.7501L18.5936 17.6164C16.4909 16.9082 14.1791 18.1618 13.7456 20.3562L13.6666 20.7562C13.5855 21.1666 13.2021 21.5 12.7136 21.5H11.2867C10.7983 21.5 10.4149 21.1667 10.3338 20.7562L10.2547 20.356C9.82113 18.1617 7.50931 16.9082 5.40665 17.6165L5.0099 17.7501C4.55092 17.9047 4.06104 17.714 3.83671 17.3373L3.1233 16.1393C2.9058 15.7741 2.97959 15.3073 3.32398 15.0186L3.64185 14.7522C5.36782 13.3056 5.36781 10.6944 3.64185 9.24779L3.32398 8.98137C2.97959 8.69273 2.9058 8.2259 3.1233 7.86067L3.83674 6.66266C4.06106 6.28596 4.55093 6.09528 5.0099 6.24986L5.40676 6.38352C7.50938 7.09166 9.82112 5.83819 10.2547 3.64392L10.3338 3.24375Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(consoleContext().state.isManualReconnectAvailable())\n {\n <cf-console-toolbar-default-button label=\"Reconnect\"\n (clicked)=\"consoleContext().console.sendReconnectRequest()\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C16.3556 22 20.0584 19.2159 21.4307 15.3332C21.6148 14.8125 21.3418 14.2412 20.8211 14.0572C20.3004 13.8731 19.7291 14.146 19.545 14.6668C18.4463 17.7753 15.4817 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C13.5516 4 14.8662 4.56117 16.1162 5.4406C16.9569 6.03212 17.7348 6.74106 18.5242 7.5H15.5C14.9477 7.5 14.5 7.94772 14.5 8.5C14.5 9.05228 14.9477 9.5 15.5 9.5H21C21.5523 9.5 22 9.05228 22 8.5V3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3V6.14371C19.1517 5.32583 18.2456 4.49337 17.267 3.80489C15.7949 2.76916 14.0847 2 12 2Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (!consoleContext().state.isViewOnly() && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Keyboard\" (clicked)=\"isKeyboardDialogOpen = true\">\n <svg fill=\"#000000\" viewBox=\"0 0 1920 1920\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M1807.059 1637.706c0 31.059-25.299 56.47-56.47 56.47H169.411c-31.172 0-56.47-25.411-56.47-56.47v-903.53c0-31.058 25.298-56.47 56.47-56.47h1581.176c31.172 0 56.47 25.412 56.47 56.47v903.53Zm-56.47-1072.941h-729.262c14.908-86.965 65.958-113.506 133.384-147.163 89.336-44.611 200.583-100.291 200.583-304.602h-112.941c0 134.513-57.939 163.426-138.24 203.633-80.301 40.094-177.544 90.24-196.518 248.132H169.412C76.009 564.765 0 640.775 0 734.176v903.53c0 93.402 76.01 169.412 169.412 169.412h1581.176c93.403 0 169.412-76.01 169.412-169.412v-903.53c0-93.402-76.01-169.411-169.412-169.411Zm-564.707 677.647H734.118c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h451.764c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.299 56.471-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m-1016.47 0H395.293c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m0-338.824h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m225.883 225.882h112.94c31.173 0 56.471-25.3 56.471-56.471V960.059c0-31.172-25.298-56.47-56.47-56.47h-112.94c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47m451.764-225.882h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.298 56.471-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47\"\n fill-rule=\"evenodd\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(!cfConfig.disabledFeatures.clipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" preserveAspectRatio=\"none\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19.5 16.5L19.5 4.5L18.75 3.75H9L8.25 4.5L8.25 7.5L5.25 7.5L4.5 8.25V20.25L5.25 21H15L15.75 20.25V17.25H18.75L19.5 16.5ZM15.75 15.75L15.75 8.25L15 7.5L9.75 7.5V5.25L18 5.25V15.75H15.75ZM6 9L14.25 9L14.25 19.5L6 19.5L6 9Z\"\n fill=\"#080341\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().networks.config()?.networks?.length) {\n <cf-console-toolbar-default-button label=\"Networks ({{ consoleContext().networks.config()?.networks?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button> }\n }\n\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (!cfConfig.disabledFeatures.consoleScreenRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <title>record [#979]</title>\n <desc>Created with Sketch.</desc>\n <defs> </defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M4 2C2.89543 2 2 2.89543 2 4V8C2 8.55228 2.44772 9 3 9C3.55228 9 4 8.55228 4 8V4H8C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2H4Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 2C21.1046 2 22 2.89543 22 4V8C22 8.55228 21.5523 9 21 9C20.4477 9 20 8.55228 20 8V4H16C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 22C21.1046 22 22 21.1046 22 20V16C22 15.4477 21.5523 15 21 15C20.4477 15 20 15.4477 20 16V20H16C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M2 20C2 21.1046 2.89543 22 4 22H8C8.55228 22 9 21.5523 9 21C9 20.4477 8.55228 20 8 20H4V16C4 15.4477 3.55228 15 3 15C2.44772 15 2 15.4477 2 16V20Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n </div>\n\n <dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Clipboard</strong>\n </p>\n </header>\n\n @if (consoleContext().console.supportedFeatures().clipboardRemoteWrite) {\n <div class=\"dialog-section\">\n <h2>Send Text to Console Clipboard</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n }\n\n @if(!consoleContext().userSettings.settings().console.allowCopyToLocalClipboard ||\n !consoleContext().console.supportedFeatures().clipboardAutomaticLocalCopy) {\n <div class=\"dialog-section\">\n <h2>Console Clipboard Content</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\" disabled\n [value]=\"consoleContext().clipboard.consoleClipboardText()\"\n placeholder=\"The console's clipboard content will appear here\" #consoleLastClipboardText>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n </form>\n </div>\n }\n </article>\n </dialog>\n\n <dialog [open]=\"isKeyboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isKeyboardDialogOpen = false\"></button>\n <p>\n <strong>Send Keystrokes</strong>\n </p>\n </header>\n\n <div class=\"dialog-section\">\n <h2>Send Keystrokes to Console</h2>\n <form (submit)=\"handleSendKeyboardInput($event, keyboardInputText())\">\n <fieldset role=\"group\">\n <input type=\"text\" name=\"keyboardInputText\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send as keyboard input to the console\" autofocus\n [(ngModel)]=\"keyboardInputText\">\n <button type=\"submit\"\n [disabled]=\"!keyboardInputText() || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n <div class=\"dialog-section\">\n <h2>Special Key Combinations</h2>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" aria-label=\"Send Ctrl+Alt+Delete\" (click)=\"handlSendKeyboardCtrlAltDel()\">\n Ctrl + Alt + Delete\n </button>\n </div>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Networks</strong>\n </p>\n </header>\n\n <form>\n @for (nic of consoleContext().networks.config()?.nics; track nic)\n {\n <label for=\"nic-{{ nic }}-select\">{{ nic }}</label>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"nic-{{ nic }}-select\"\n aria-label=\"Select a network to connect to\">\n <option [selected]=\"!consoleContext().networks.config()?.currentConnections?.[nic]\" value=\"\">\n [Disconnected]\n </option>\n\n @for(network of consoleContext().networks.config()?.networks; track network) {\n <option [value]=\"network\"\n [selected]=\"consoleContext().networks.config()?.currentConnections?.[nic] === network\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\"\n (click)=\"handleNetworkChangeRequested({ network: availableNetworksSelect.value, nic: nic })\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n }\n <hr />\n <div class=\"dialog-button-group\">\n <button class=\"secondary\" type=\"button\" (click)=\"handleNetworkDisconnectAllRequested()\">\n Disconnect All Network Interfaces\n </button>\n </div>\n </form>\n </article>\n </dialog>\n\n <dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Power</strong>\n </p>\n </header>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputAttemptRemoteSessionResize type=\"checkbox\" name=\"attemptRemoteSessionResize\"\n [checked]=\"consoleContext().userSettings.settings().console.attemptRemoteSessionResize\"\n (change)=\"handleSettingsAttemptRemoteSessionResize(inputAttemptRemoteSessionResize.checked)\" />\n Attempt to resize the remote session to match local resolution\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.scaleToCanvasHostSize\"\n (change)=\"handleSettingsScaleToContainerHostSize(inputScaleToContainerSize.checked)\" />\n Scale to maximum available size\n </label>\n </fieldset>\n\n <div class=\"settings-toolbar-dock\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <!-- see https://github.com/cmu-sei/console-forge/issues/12 -->\n <!-- <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button> -->\n </div>\n </div>\n\n <div class=\"settings-theme\">\n <h4>Theme</h4>\n <div role=\"group\">\n <button (click)=\"handleToolbarThemeChange('light')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'light'\">Light</button>\n <button (click)=\"handleToolbarThemeChange('dark')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'dark'\">Dark</button>\n <button (click)=\"handleToolbarThemeChange(undefined)\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === undefined\">\n My Default\n </button>\n </div>\n </div>\n </div>\n </article>\n </dialog>\n</div>\n}\n", styles: [":host{display:block;height:100%;width:100%;max-width:100%}fieldset legend{font-weight:700}.toolbar-container{background-color:var(--pico-background-color);padding:4px;height:100%;display:flex;align-items:center;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-color);margin:.25rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{align-self:stretch;border-left:1px solid var(--pico-color);height:auto;margin:0 1rem;width:1px}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.settings-toolbar-dock{margin-top:1rem}dialog h2{font-size:1.1rem;font-weight:700}dialog .dialog-section:not(:last-of-type){margin-bottom:1.5rem}dialog .dialog-button-group button{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: ApplyToolbarThemeDirective, selector: "[cfApplyToolbarTheme]" }, { kind: "component", type: ConsoleToolbarDefaultButtonComponent, selector: "cf-console-toolbar-default-button", inputs: ["disabled", "label", "isOngoing"], outputs: ["clicked"] }], encapsulation: i0.ViewEncapsulation.ShadowDom });
422
429
  }
423
430
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultComponent, decorators: [{
424
431
  type: Component,
@@ -426,7 +433,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
426
433
  FormsModule,
427
434
  ApplyToolbarThemeDirective,
428
435
  ConsoleToolbarDefaultButtonComponent
429
- ], standalone: true, encapsulation: ViewEncapsulation.ShadowDom, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\" cfApplyToolbarTheme\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12.0002 8C9.79111 8 8.00024 9.79086 8.00024 12C8.00024 14.2091 9.79111 16 12.0002 16C14.2094 16 16.0002 14.2091 16.0002 12C16.0002 9.79086 14.2094 8 12.0002 8ZM10.0002 12C10.0002 10.8954 10.8957 10 12.0002 10C13.1048 10 14.0002 10.8954 14.0002 12C14.0002 13.1046 13.1048 14 12.0002 14C10.8957 14 10.0002 13.1046 10.0002 12Z\"\n fill=\"#000000\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.2867 0.5C9.88583 0.5 8.6461 1.46745 8.37171 2.85605L8.29264 3.25622C8.10489 4.20638 7.06195 4.83059 6.04511 4.48813L5.64825 4.35447C4.32246 3.90796 2.83873 4.42968 2.11836 5.63933L1.40492 6.83735C0.67773 8.05846 0.954349 9.60487 2.03927 10.5142L2.35714 10.7806C3.12939 11.4279 3.12939 12.5721 2.35714 13.2194L2.03927 13.4858C0.954349 14.3951 0.67773 15.9415 1.40492 17.1626L2.11833 18.3606C2.83872 19.5703 4.3225 20.092 5.64831 19.6455L6.04506 19.5118C7.06191 19.1693 8.1049 19.7935 8.29264 20.7437L8.37172 21.1439C8.6461 22.5325 9.88584 23.5 11.2867 23.5H12.7136C14.1146 23.5 15.3543 22.5325 15.6287 21.1438L15.7077 20.7438C15.8954 19.7936 16.9384 19.1693 17.9553 19.5118L18.3521 19.6455C19.6779 20.092 21.1617 19.5703 21.8821 18.3606L22.5955 17.1627C23.3227 15.9416 23.046 14.3951 21.9611 13.4858L21.6432 13.2194C20.8709 12.5722 20.8709 11.4278 21.6432 10.7806L21.9611 10.5142C23.046 9.60489 23.3227 8.05845 22.5955 6.83732L21.8821 5.63932C21.1617 4.42968 19.678 3.90795 18.3522 4.35444L17.9552 4.48814C16.9384 4.83059 15.8954 4.20634 15.7077 3.25617L15.6287 2.85616C15.3543 1.46751 14.1146 0.5 12.7136 0.5H11.2867ZM10.3338 3.24375C10.4149 2.83334 10.7983 2.5 11.2867 2.5H12.7136C13.2021 2.5 13.5855 2.83336 13.6666 3.24378L13.7456 3.64379C14.1791 5.83811 16.4909 7.09167 18.5935 6.38353L18.9905 6.24984C19.4495 6.09527 19.9394 6.28595 20.1637 6.66264L20.8771 7.86064C21.0946 8.22587 21.0208 8.69271 20.6764 8.98135L20.3586 9.24773C18.6325 10.6943 18.6325 13.3057 20.3586 14.7523L20.6764 15.0186C21.0208 15.3073 21.0946 15.7741 20.8771 16.1394L20.1637 17.3373C19.9394 17.714 19.4495 17.9047 18.9905 17.7501L18.5936 17.6164C16.4909 16.9082 14.1791 18.1618 13.7456 20.3562L13.6666 20.7562C13.5855 21.1666 13.2021 21.5 12.7136 21.5H11.2867C10.7983 21.5 10.4149 21.1667 10.3338 20.7562L10.2547 20.356C9.82113 18.1617 7.50931 16.9082 5.40665 17.6165L5.0099 17.7501C4.55092 17.9047 4.06104 17.714 3.83671 17.3373L3.1233 16.1393C2.9058 15.7741 2.97959 15.3073 3.32398 15.0186L3.64185 14.7522C5.36782 13.3056 5.36781 10.6944 3.64185 9.24779L3.32398 8.98137C2.97959 8.69273 2.9058 8.2259 3.1233 7.86067L3.83674 6.66266C4.06106 6.28596 4.55093 6.09528 5.0099 6.24986L5.40676 6.38352C7.50938 7.09166 9.82112 5.83819 10.2547 3.64392L10.3338 3.24375Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(consoleContext().state.isManualReconnectAvailable())\n {\n <cf-console-toolbar-default-button label=\"Reconnect\"\n (clicked)=\"consoleContext().console.sendReconnectRequest()\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C16.3556 22 20.0584 19.2159 21.4307 15.3332C21.6148 14.8125 21.3418 14.2412 20.8211 14.0572C20.3004 13.8731 19.7291 14.146 19.545 14.6668C18.4463 17.7753 15.4817 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C13.5516 4 14.8662 4.56117 16.1162 5.4406C16.9569 6.03212 17.7348 6.74106 18.5242 7.5H15.5C14.9477 7.5 14.5 7.94772 14.5 8.5C14.5 9.05228 14.9477 9.5 15.5 9.5H21C21.5523 9.5 22 9.05228 22 8.5V3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3V6.14371C19.1517 5.32583 18.2456 4.49337 17.267 3.80489C15.7949 2.76916 14.0847 2 12 2Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (!consoleContext().state.isViewOnly() && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Keyboard\" (clicked)=\"isKeyboardDialogOpen = true\">\n <svg fill=\"#000000\" viewBox=\"0 0 1920 1920\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M1807.059 1637.706c0 31.059-25.299 56.47-56.47 56.47H169.411c-31.172 0-56.47-25.411-56.47-56.47v-903.53c0-31.058 25.298-56.47 56.47-56.47h1581.176c31.172 0 56.47 25.412 56.47 56.47v903.53Zm-56.47-1072.941h-729.262c14.908-86.965 65.958-113.506 133.384-147.163 89.336-44.611 200.583-100.291 200.583-304.602h-112.941c0 134.513-57.939 163.426-138.24 203.633-80.301 40.094-177.544 90.24-196.518 248.132H169.412C76.009 564.765 0 640.775 0 734.176v903.53c0 93.402 76.01 169.412 169.412 169.412h1581.176c93.403 0 169.412-76.01 169.412-169.412v-903.53c0-93.402-76.01-169.411-169.412-169.411Zm-564.707 677.647H734.118c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h451.764c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.299 56.471-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m-1016.47 0H395.293c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m0-338.824h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m225.883 225.882h112.94c31.173 0 56.471-25.3 56.471-56.471V960.059c0-31.172-25.298-56.47-56.47-56.47h-112.94c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47m451.764-225.882h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.298 56.471-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47\"\n fill-rule=\"evenodd\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(!cfConfig.disabledFeatures.clipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" preserveAspectRatio=\"none\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19.5 16.5L19.5 4.5L18.75 3.75H9L8.25 4.5L8.25 7.5L5.25 7.5L4.5 8.25V20.25L5.25 21H15L15.75 20.25V17.25H18.75L19.5 16.5ZM15.75 15.75L15.75 8.25L15 7.5L9.75 7.5V5.25L18 5.25V15.75H15.75ZM6 9L14.25 9L14.25 19.5L6 19.5L6 9Z\"\n fill=\"#080341\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().networks.config()?.available?.length) {\n <cf-console-toolbar-default-button\n label=\"Networks ({{ consoleContext().networks.config()?.available?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button> }\n }\n\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (!cfConfig.disabledFeatures.consoleScreenRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <title>record [#979]</title>\n <desc>Created with Sketch.</desc>\n <defs> </defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M4 2C2.89543 2 2 2.89543 2 4V8C2 8.55228 2.44772 9 3 9C3.55228 9 4 8.55228 4 8V4H8C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2H4Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 2C21.1046 2 22 2.89543 22 4V8C22 8.55228 21.5523 9 21 9C20.4477 9 20 8.55228 20 8V4H16C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 22C21.1046 22 22 21.1046 22 20V16C22 15.4477 21.5523 15 21 15C20.4477 15 20 15.4477 20 16V20H16C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M2 20C2 21.1046 2.89543 22 4 22H8C8.55228 22 9 21.5523 9 21C9 20.4477 8.55228 20 8 20H4V16C4 15.4477 3.55228 15 3 15C2.44772 15 2 15.4477 2 16V20Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n </div>\n\n <dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Clipboard</strong>\n </p>\n </header>\n\n @if (consoleContext().console.supportedFeatures().clipboardRemoteWrite) {\n <div class=\"dialog-section\">\n <h2>Send Text to Console Clipboard</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n }\n\n @if(!consoleContext().userSettings.settings().console.allowCopyToLocalClipboard ||\n !consoleContext().console.supportedFeatures().clipboardAutomaticLocalCopy) {\n <div class=\"dialog-section\">\n <h2>Console Clipboard Content</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\" disabled\n [value]=\"consoleContext().clipboard.consoleClipboardText()\"\n placeholder=\"The console's clipboard content will appear here\" #consoleLastClipboardText>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n </form>\n </div>\n }\n </article>\n </dialog>\n\n <dialog [open]=\"isKeyboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isKeyboardDialogOpen = false\"></button>\n <p>\n <strong>Send Keystrokes</strong>\n </p>\n </header>\n\n <div class=\"dialog-section\">\n <h2>Send Keystrokes to Console</h2>\n <form (submit)=\"handleSendKeyboardInput($event, keyboardInputText())\">\n <fieldset role=\"group\">\n <input type=\"text\" name=\"keyboardInputText\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send as keyboard input to the console\" autofocus\n [(ngModel)]=\"keyboardInputText\">\n <button type=\"submit\"\n [disabled]=\"!keyboardInputText() || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n <div class=\"dialog-section\">\n <h2>Special Key Combinations</h2>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" aria-label=\"Send Ctrl+Alt+Delete\" (click)=\"handlSendKeyboardCtrlAltDel()\">\n Ctrl + Alt + Delete\n </button>\n </div>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Networks</strong>\n </p>\n </header>\n\n <form>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"current-network\" aria-label=\"Select a network to connect to\"\n [(ngModel)]=\"selectedNetworkForChange\" required>\n <option selected value=\"\">\n [Disconnect from network]\n </option>\n\n @for(network of consoleContext().networks.config()?.available; track network) {\n <option [value]=\"network\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\" (click)=\"handleNetworkChangeRequested(selectedNetworkForChange())\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n </form>\n </article>\n </dialog>\n\n <dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Power</strong>\n </p>\n </header>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.preserveAspectRatioOnScale\"\n (change)=\"handleSettingsPreserveAspectRatioChange(inputScaleToContainerSize.checked)\" />\n Preserve console aspect ratio when scaling size\n </label>\n </fieldset>\n\n <div class=\"settings-toolbar-dock\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <!-- see https://github.com/cmu-sei/console-forge/issues/12 -->\n <!-- <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button> -->\n </div>\n </div>\n\n <div class=\"settings-theme\">\n <h4>Theme</h4>\n <div role=\"group\">\n <button (click)=\"handleToolbarThemeChange('light')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'light'\">Light</button>\n <button (click)=\"handleToolbarThemeChange('dark')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'dark'\">Dark</button>\n <button (click)=\"handleToolbarThemeChange(undefined)\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === undefined\">\n My Default\n </button>\n </div>\n </div>\n </div>\n </article>\n </dialog>\n</div>\n}\n", styles: [":host{display:block;height:100%;width:100%;max-width:100%}fieldset legend{font-weight:700}.toolbar-container{background-color:var(--pico-background-color);padding:4px;height:100%;display:flex;align-items:center;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-color);margin:.25rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{align-self:stretch;border-left:1px solid var(--pico-color);height:auto;margin:0 1rem;width:1px}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.settings-toolbar-dock{margin-top:1rem}dialog h2{font-size:1.1rem;font-weight:700}dialog .dialog-section:not(:last-of-type){margin-bottom:1.5rem}dialog .dialog-button-group button{display:block;width:100%}\n"] }]
436
+ ], standalone: true, encapsulation: ViewEncapsulation.ShadowDom, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\" cfApplyToolbarTheme\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12.0002 8C9.79111 8 8.00024 9.79086 8.00024 12C8.00024 14.2091 9.79111 16 12.0002 16C14.2094 16 16.0002 14.2091 16.0002 12C16.0002 9.79086 14.2094 8 12.0002 8ZM10.0002 12C10.0002 10.8954 10.8957 10 12.0002 10C13.1048 10 14.0002 10.8954 14.0002 12C14.0002 13.1046 13.1048 14 12.0002 14C10.8957 14 10.0002 13.1046 10.0002 12Z\"\n fill=\"#000000\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.2867 0.5C9.88583 0.5 8.6461 1.46745 8.37171 2.85605L8.29264 3.25622C8.10489 4.20638 7.06195 4.83059 6.04511 4.48813L5.64825 4.35447C4.32246 3.90796 2.83873 4.42968 2.11836 5.63933L1.40492 6.83735C0.67773 8.05846 0.954349 9.60487 2.03927 10.5142L2.35714 10.7806C3.12939 11.4279 3.12939 12.5721 2.35714 13.2194L2.03927 13.4858C0.954349 14.3951 0.67773 15.9415 1.40492 17.1626L2.11833 18.3606C2.83872 19.5703 4.3225 20.092 5.64831 19.6455L6.04506 19.5118C7.06191 19.1693 8.1049 19.7935 8.29264 20.7437L8.37172 21.1439C8.6461 22.5325 9.88584 23.5 11.2867 23.5H12.7136C14.1146 23.5 15.3543 22.5325 15.6287 21.1438L15.7077 20.7438C15.8954 19.7936 16.9384 19.1693 17.9553 19.5118L18.3521 19.6455C19.6779 20.092 21.1617 19.5703 21.8821 18.3606L22.5955 17.1627C23.3227 15.9416 23.046 14.3951 21.9611 13.4858L21.6432 13.2194C20.8709 12.5722 20.8709 11.4278 21.6432 10.7806L21.9611 10.5142C23.046 9.60489 23.3227 8.05845 22.5955 6.83732L21.8821 5.63932C21.1617 4.42968 19.678 3.90795 18.3522 4.35444L17.9552 4.48814C16.9384 4.83059 15.8954 4.20634 15.7077 3.25617L15.6287 2.85616C15.3543 1.46751 14.1146 0.5 12.7136 0.5H11.2867ZM10.3338 3.24375C10.4149 2.83334 10.7983 2.5 11.2867 2.5H12.7136C13.2021 2.5 13.5855 2.83336 13.6666 3.24378L13.7456 3.64379C14.1791 5.83811 16.4909 7.09167 18.5935 6.38353L18.9905 6.24984C19.4495 6.09527 19.9394 6.28595 20.1637 6.66264L20.8771 7.86064C21.0946 8.22587 21.0208 8.69271 20.6764 8.98135L20.3586 9.24773C18.6325 10.6943 18.6325 13.3057 20.3586 14.7523L20.6764 15.0186C21.0208 15.3073 21.0946 15.7741 20.8771 16.1394L20.1637 17.3373C19.9394 17.714 19.4495 17.9047 18.9905 17.7501L18.5936 17.6164C16.4909 16.9082 14.1791 18.1618 13.7456 20.3562L13.6666 20.7562C13.5855 21.1666 13.2021 21.5 12.7136 21.5H11.2867C10.7983 21.5 10.4149 21.1667 10.3338 20.7562L10.2547 20.356C9.82113 18.1617 7.50931 16.9082 5.40665 17.6165L5.0099 17.7501C4.55092 17.9047 4.06104 17.714 3.83671 17.3373L3.1233 16.1393C2.9058 15.7741 2.97959 15.3073 3.32398 15.0186L3.64185 14.7522C5.36782 13.3056 5.36781 10.6944 3.64185 9.24779L3.32398 8.98137C2.97959 8.69273 2.9058 8.2259 3.1233 7.86067L3.83674 6.66266C4.06106 6.28596 4.55093 6.09528 5.0099 6.24986L5.40676 6.38352C7.50938 7.09166 9.82112 5.83819 10.2547 3.64392L10.3338 3.24375Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(consoleContext().state.isManualReconnectAvailable())\n {\n <cf-console-toolbar-default-button label=\"Reconnect\"\n (clicked)=\"consoleContext().console.sendReconnectRequest()\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C16.3556 22 20.0584 19.2159 21.4307 15.3332C21.6148 14.8125 21.3418 14.2412 20.8211 14.0572C20.3004 13.8731 19.7291 14.146 19.545 14.6668C18.4463 17.7753 15.4817 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C13.5516 4 14.8662 4.56117 16.1162 5.4406C16.9569 6.03212 17.7348 6.74106 18.5242 7.5H15.5C14.9477 7.5 14.5 7.94772 14.5 8.5C14.5 9.05228 14.9477 9.5 15.5 9.5H21C21.5523 9.5 22 9.05228 22 8.5V3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3V6.14371C19.1517 5.32583 18.2456 4.49337 17.267 3.80489C15.7949 2.76916 14.0847 2 12 2Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (!consoleContext().state.isViewOnly() && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Keyboard\" (clicked)=\"isKeyboardDialogOpen = true\">\n <svg fill=\"#000000\" viewBox=\"0 0 1920 1920\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M1807.059 1637.706c0 31.059-25.299 56.47-56.47 56.47H169.411c-31.172 0-56.47-25.411-56.47-56.47v-903.53c0-31.058 25.298-56.47 56.47-56.47h1581.176c31.172 0 56.47 25.412 56.47 56.47v903.53Zm-56.47-1072.941h-729.262c14.908-86.965 65.958-113.506 133.384-147.163 89.336-44.611 200.583-100.291 200.583-304.602h-112.941c0 134.513-57.939 163.426-138.24 203.633-80.301 40.094-177.544 90.24-196.518 248.132H169.412C76.009 564.765 0 640.775 0 734.176v903.53c0 93.402 76.01 169.412 169.412 169.412h1581.176c93.403 0 169.412-76.01 169.412-169.412v-903.53c0-93.402-76.01-169.411-169.412-169.411Zm-564.707 677.647H734.118c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h451.764c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.299 56.471-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m-1016.47 0H395.293c-31.172 0-56.47 25.299-56.47 56.47v112.942c0 31.171 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.299 56.47-56.47v-112.942c0-31.171-25.298-56.47-56.47-56.47m0-338.824h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m225.883 225.882h112.94c31.173 0 56.471-25.3 56.471-56.471V960.059c0-31.172-25.298-56.47-56.47-56.47h-112.94c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47m451.764-225.882h-112.94c-31.173 0-56.471 25.3-56.471 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.941c31.172 0 56.47-25.298 56.47-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47m338.824 0h-112.941c-31.172 0-56.47 25.298-56.47 56.47V1073c0 31.172 25.298 56.47 56.47 56.47h112.94c31.173 0 56.471-25.298 56.471-56.47V960.059c0-31.172-25.298-56.47-56.47-56.47\"\n fill-rule=\"evenodd\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if(!cfConfig.disabledFeatures.clipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" preserveAspectRatio=\"none\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19.5 16.5L19.5 4.5L18.75 3.75H9L8.25 4.5L8.25 7.5L5.25 7.5L4.5 8.25V20.25L5.25 21H15L15.75 20.25V17.25H18.75L19.5 16.5ZM15.75 15.75L15.75 8.25L15 7.5L9.75 7.5V5.25L18 5.25V15.75H15.75ZM6 9L14.25 9L14.25 19.5L6 19.5L6 9Z\"\n fill=\"#080341\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().networks.config()?.networks?.length) {\n <cf-console-toolbar-default-button label=\"Networks ({{ consoleContext().networks.config()?.networks?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button> }\n }\n\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (!cfConfig.disabledFeatures.consoleScreenRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <title>record [#979]</title>\n <desc>Created with Sketch.</desc>\n <defs> </defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M4 2C2.89543 2 2 2.89543 2 4V8C2 8.55228 2.44772 9 3 9C3.55228 9 4 8.55228 4 8V4H8C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2H4Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 2C21.1046 2 22 2.89543 22 4V8C22 8.55228 21.5523 9 21 9C20.4477 9 20 8.55228 20 8V4H16C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M20 22C21.1046 22 22 21.1046 22 20V16C22 15.4477 21.5523 15 21 15C20.4477 15 20 15.4477 20 16V20H16C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H20Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M2 20C2 21.1046 2.89543 22 4 22H8C8.55228 22 9 21.5523 9 21C9 20.4477 8.55228 20 8 20H4V16C4 15.4477 3.55228 15 3 15C2.44772 15 2 15.4477 2 16V20Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\"></path>\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\"></path>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n </div>\n\n <dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Clipboard</strong>\n </p>\n </header>\n\n @if (consoleContext().console.supportedFeatures().clipboardRemoteWrite) {\n <div class=\"dialog-section\">\n <h2>Send Text to Console Clipboard</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n }\n\n @if(!consoleContext().userSettings.settings().console.allowCopyToLocalClipboard ||\n !consoleContext().console.supportedFeatures().clipboardAutomaticLocalCopy) {\n <div class=\"dialog-section\">\n <h2>Console Clipboard Content</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\" disabled\n [value]=\"consoleContext().clipboard.consoleClipboardText()\"\n placeholder=\"The console's clipboard content will appear here\" #consoleLastClipboardText>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n </form>\n </div>\n }\n </article>\n </dialog>\n\n <dialog [open]=\"isKeyboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isKeyboardDialogOpen = false\"></button>\n <p>\n <strong>Send Keystrokes</strong>\n </p>\n </header>\n\n <div class=\"dialog-section\">\n <h2>Send Keystrokes to Console</h2>\n <form (submit)=\"handleSendKeyboardInput($event, keyboardInputText())\">\n <fieldset role=\"group\">\n <input type=\"text\" name=\"keyboardInputText\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send as keyboard input to the console\" autofocus\n [(ngModel)]=\"keyboardInputText\">\n <button type=\"submit\"\n [disabled]=\"!keyboardInputText() || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n <div class=\"dialog-section\">\n <h2>Special Key Combinations</h2>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" aria-label=\"Send Ctrl+Alt+Delete\" (click)=\"handlSendKeyboardCtrlAltDel()\">\n Ctrl + Alt + Delete\n </button>\n </div>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Networks</strong>\n </p>\n </header>\n\n <form>\n @for (nic of consoleContext().networks.config()?.nics; track nic)\n {\n <label for=\"nic-{{ nic }}-select\">{{ nic }}</label>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"nic-{{ nic }}-select\"\n aria-label=\"Select a network to connect to\">\n <option [selected]=\"!consoleContext().networks.config()?.currentConnections?.[nic]\" value=\"\">\n [Disconnected]\n </option>\n\n @for(network of consoleContext().networks.config()?.networks; track network) {\n <option [value]=\"network\"\n [selected]=\"consoleContext().networks.config()?.currentConnections?.[nic] === network\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\"\n (click)=\"handleNetworkChangeRequested({ network: availableNetworksSelect.value, nic: nic })\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n }\n <hr />\n <div class=\"dialog-button-group\">\n <button class=\"secondary\" type=\"button\" (click)=\"handleNetworkDisconnectAllRequested()\">\n Disconnect All Network Interfaces\n </button>\n </div>\n </form>\n </article>\n </dialog>\n\n <dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Power</strong>\n </p>\n </header>\n\n <div class=\"dialog-button-group\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n </dialog>\n\n <dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputAttemptRemoteSessionResize type=\"checkbox\" name=\"attemptRemoteSessionResize\"\n [checked]=\"consoleContext().userSettings.settings().console.attemptRemoteSessionResize\"\n (change)=\"handleSettingsAttemptRemoteSessionResize(inputAttemptRemoteSessionResize.checked)\" />\n Attempt to resize the remote session to match local resolution\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.scaleToCanvasHostSize\"\n (change)=\"handleSettingsScaleToContainerHostSize(inputScaleToContainerSize.checked)\" />\n Scale to maximum available size\n </label>\n </fieldset>\n\n <div class=\"settings-toolbar-dock\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <!-- see https://github.com/cmu-sei/console-forge/issues/12 -->\n <!-- <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button> -->\n </div>\n </div>\n\n <div class=\"settings-theme\">\n <h4>Theme</h4>\n <div role=\"group\">\n <button (click)=\"handleToolbarThemeChange('light')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'light'\">Light</button>\n <button (click)=\"handleToolbarThemeChange('dark')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === 'dark'\">Dark</button>\n <button (click)=\"handleToolbarThemeChange(undefined)\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.preferTheme === undefined\">\n My Default\n </button>\n </div>\n </div>\n </div>\n </article>\n </dialog>\n</div>\n}\n", styles: [":host{display:block;height:100%;width:100%;max-width:100%}fieldset legend{font-weight:700}.toolbar-container{background-color:var(--pico-background-color);padding:4px;height:100%;display:flex;align-items:center;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-color);margin:.25rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{align-self:stretch;border-left:1px solid var(--pico-color);height:auto;margin:0 1rem;width:1px}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.settings-toolbar-dock{margin-top:1rem}dialog h2{font-size:1.1rem;font-weight:700}dialog .dialog-section:not(:last-of-type){margin-bottom:1.5rem}dialog .dialog-button-group button{display:block;width:100%}\n"] }]
430
437
  }], ctorParameters: () => [] });
431
438
 
432
439
  // ===BEGIN LICENSE===
@@ -472,6 +479,7 @@ class VncConsoleClientService {
472
479
  clipboardRemoteWrite: true,
473
480
  onScreenKeyboard: false,
474
481
  powerManagement: false,
482
+ requireReconnectOnExitingFullscreen: true,
475
483
  viewOnlyMode: true
476
484
  });
477
485
  supportedFeatures = this._supportedFeatures.asReadonly();
@@ -482,7 +490,17 @@ class VncConsoleClientService {
482
490
  userSettings = inject(UserSettingsService);
483
491
  // the actual client from @novnc/novnc
484
492
  noVncClient;
485
- async connect(url, options) {
493
+ constructor() {
494
+ // listen for user settings changes so we can update the console
495
+ effect(() => {
496
+ const settings = this.userSettings.settings();
497
+ if (!this.noVncClient) {
498
+ return;
499
+ }
500
+ this.updateFromUserSettings(this.noVncClient, settings);
501
+ });
502
+ }
503
+ connect(url, options) {
486
504
  if (this.noVncClient) {
487
505
  try {
488
506
  this.noVncClient.disconnect();
@@ -493,47 +511,62 @@ class VncConsoleClientService {
493
511
  }
494
512
  this.noVncClient = undefined;
495
513
  }
496
- try {
497
- this._connectionStatus.update(() => "connecting");
498
- this.logger.log(LogLevel.DEBUG, "Connecting to", url, options);
499
- const noVncCredentials = {
500
- credentials: {
501
- password: options?.credentials?.accessTicket || options?.credentials?.password || "",
502
- // explicitly not supporting these for now
503
- username: "",
504
- target: ""
505
- },
506
- };
507
- this.logger.log(LogLevel.DEBUG, "Connecting...", noVncCredentials);
508
- let client = new NoVncClient(options.hostElement, url, noVncCredentials);
509
- this.logger.log(LogLevel.DEBUG, "Client instantiated. Configuring...");
510
- client = this.doPreConnectionConfig(client);
511
- this.logger.log(LogLevel.DEBUG, "Pre-connection config done.");
512
- client.addEventListener("connect", () => {
513
- this._connectionStatus.update(() => "connected");
514
- this.logger.log(LogLevel.DEBUG, "Connected. Performing post-connection configuration...");
515
- // do other post-connection config
516
- this.noVncClient = this.doPostConnectionConfig(client, options);
517
- this.logger.log(LogLevel.DEBUG, "Post-connection config done. Resolving supported features...");
518
- // the vnc client knows its capabilities post-connection
519
- // so send this back along with the things we know we can't support
520
- const supportedFeatures = {
521
- clipboardAutomaticLocalCopy: true,
522
- clipboardRemoteWrite: true,
523
- onScreenKeyboard: false,
524
- powerManagement: this.noVncClient.capabilities.power,
525
- viewOnlyMode: true
514
+ return new Promise((resolve, reject) => {
515
+ // track whether we've resolved the promise yet - we need to reject it on the "disconnect" event if it isn't
516
+ let isResolved = false;
517
+ try {
518
+ this._connectionStatus.update(() => "connecting");
519
+ this.logger.log(LogLevel.DEBUG, "Connecting to", url, options);
520
+ const noVncCredentials = {
521
+ credentials: {
522
+ password: options?.credentials?.accessTicket || options?.credentials?.password || "",
523
+ // explicitly not supporting these for now
524
+ username: "",
525
+ target: ""
526
+ },
526
527
  };
527
- this._supportedFeatures.update(() => supportedFeatures);
528
- this.noVncClient = client;
529
- this.logger.log(LogLevel.DEBUG, "Supported features resolved. Connection complete!");
530
- });
531
- }
532
- catch (err) {
533
- this._connectionStatus.update(() => "disconnected");
534
- this.logger.log(LogLevel.ERROR, "Connection error", err);
535
- throw err;
536
- }
528
+ this.logger.log(LogLevel.DEBUG, "Connecting...", noVncCredentials);
529
+ const client = new NoVncClient(options.hostElement, url, noVncCredentials);
530
+ this.logger.log(LogLevel.DEBUG, "Client instantiated. Configuring...");
531
+ this.doPreConnectionConfig(client);
532
+ this.logger.log(LogLevel.DEBUG, "Pre-connection config done.");
533
+ client.addEventListener("disconnect", event => {
534
+ if (isResolved) {
535
+ return;
536
+ }
537
+ isResolved = true;
538
+ this.logger.log(LogLevel.ERROR, "Connection error", event);
539
+ reject(event);
540
+ });
541
+ client.addEventListener("connect", () => {
542
+ this._connectionStatus.update(() => "connected");
543
+ this.logger.log(LogLevel.DEBUG, "Connected. Performing post-connection configuration...");
544
+ // do other post-connection config
545
+ this.doPostConnectionConfig(client, options);
546
+ this.logger.log(LogLevel.DEBUG, "Post-connection config done. Resolving supported features...");
547
+ // the vnc client knows its capabilities post-connection
548
+ // so send this back along with the things we know we can't support
549
+ const supportedFeatures = {
550
+ clipboardAutomaticLocalCopy: true,
551
+ clipboardRemoteWrite: true,
552
+ onScreenKeyboard: false,
553
+ powerManagement: client.capabilities.power,
554
+ requireReconnectOnExitingFullscreen: true,
555
+ viewOnlyMode: true
556
+ };
557
+ this._supportedFeatures.update(() => supportedFeatures);
558
+ this.noVncClient = client;
559
+ this.logger.log(LogLevel.DEBUG, "Connection complete!", this.noVncClient);
560
+ isResolved = true;
561
+ resolve();
562
+ });
563
+ }
564
+ catch (err) {
565
+ this._connectionStatus.update(() => "disconnected");
566
+ this.logger.log(LogLevel.ERROR, "Connection error", err);
567
+ reject(err);
568
+ }
569
+ });
537
570
  }
538
571
  async disconnect() {
539
572
  if (!this.noVncClient) {
@@ -546,15 +579,6 @@ class VncConsoleClientService {
546
579
  async dispose() {
547
580
  return await this.disconnect();
548
581
  }
549
- handlePostFullscreenChange() {
550
- // setTimeout(() => {
551
- // this.noVncClient?.blur();
552
- // setTimeout(() => {
553
- // this.noVncClient?.focus({});
554
- // this.logger.log(LogLevel.DEBUG, "Blurred/focused the console after fullscreen change");
555
- // }, 500);
556
- // }, 500);
557
- }
558
582
  async sendClipboardText(text) {
559
583
  if (!this.noVncClient) {
560
584
  throw new Error("VNC client isn't connected; can't send clipboard text.");
@@ -610,17 +634,10 @@ class VncConsoleClientService {
610
634
  }
611
635
  async setIsViewOnly(isViewOnly) {
612
636
  if (!this.noVncClient) {
613
- throw new Error("VNC client isn't connected; can't set properties");
637
+ throw new Error("VNC client isn't connected; can't set properties.");
614
638
  }
615
639
  this.noVncClient.viewOnly = isViewOnly;
616
640
  }
617
- async setPreserveAspectRatioOnScale(preserve) {
618
- if (!this.noVncClient) {
619
- throw new Error("VNC client isn't connected; can't set properties");
620
- }
621
- this.logger.log(LogLevel.DEBUG, "Set preserve aspect ratio to", preserve);
622
- this.noVncClient.scaleViewport = preserve;
623
- }
624
641
  doPreConnectionConfig(client) {
625
642
  client.addEventListener("connect", () => {
626
643
  this._connectionStatus.update(() => "connected");
@@ -644,18 +661,15 @@ class VncConsoleClientService {
644
661
  this.clipboardService.copyText(ev.detail.text);
645
662
  }
646
663
  });
647
- return client;
648
664
  }
649
665
  doPostConnectionConfig(client, options) {
650
666
  client.background = options.backgroundStyle || "";
651
- // dictates whether the remote machine will be sent a request to change its resolution when the client size changes.
652
- // for now, assume we always want this.
653
- client.resizeSession = true;
654
667
  // try focus if requested
655
668
  if (options.autoFocusOnConnect) {
656
669
  client.focus();
657
670
  }
658
- return client;
671
+ // set client settings from user's
672
+ this.updateFromUserSettings(client, this.userSettings.settings());
659
673
  }
660
674
  handleDisconnect(isManualDisconnect) {
661
675
  this.logger.log(LogLevel.INFO, "Disconnected. Manual?", isManualDisconnect);
@@ -667,13 +681,25 @@ class VncConsoleClientService {
667
681
  this.noVncClient = undefined;
668
682
  }
669
683
  }
684
+ updateFromUserSettings(client, settings) {
685
+ if (!client) {
686
+ return;
687
+ }
688
+ try {
689
+ client.scaleViewport = settings.console.scaleToCanvasHostSize;
690
+ client.resizeSession = settings.console.attemptRemoteSessionResize;
691
+ }
692
+ catch (err) {
693
+ this.logger.log(LogLevel.WARNING, "Couldn't update VNC client settings from user settings.", err);
694
+ }
695
+ }
670
696
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
671
697
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, providedIn: 'root' });
672
698
  }
673
699
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, decorators: [{
674
700
  type: Injectable,
675
701
  args: [{ providedIn: 'root' }]
676
- }] });
702
+ }], ctorParameters: () => [] });
677
703
 
678
704
  // ===BEGIN LICENSE===
679
705
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
@@ -762,6 +788,16 @@ class VmWareConsoleClientService {
762
788
  }
763
789
  }
764
790
  });
791
+ constructor() {
792
+ // listen for user settings changes so we can update the console
793
+ effect(() => {
794
+ const settings = this.userSettings.settings();
795
+ if (!this.wmksClient) {
796
+ return;
797
+ }
798
+ this.updateFromUserSettings(settings);
799
+ });
800
+ }
765
801
  connect(url, options) {
766
802
  if (!options.hostElement) {
767
803
  throw new Error("A host element is required to connect to a VMWare WMKS console.");
@@ -769,7 +805,7 @@ class VmWareConsoleClientService {
769
805
  return new Promise((resolve, reject) => {
770
806
  this.wmksClient = createWmksClient(options.hostElement.id, {
771
807
  changeResolution: true,
772
- rescale: true,
808
+ rescale: false,
773
809
  useNativePixels: true,
774
810
  useVNCHandshake: false,
775
811
  position: WmksPosition.CENTER
@@ -829,8 +865,6 @@ class VmWareConsoleClientService {
829
865
  }
830
866
  return Promise.resolve();
831
867
  }
832
- handlePostFullscreenChange() {
833
- }
834
868
  async sendClipboardText(text) {
835
869
  throw new Error(`Can't send clipboard text to VMWare-based consoles. (text: ${text})`);
836
870
  }
@@ -870,20 +904,6 @@ class VmWareConsoleClientService {
870
904
  this.logger.log(LogLevel.INFO, "A 'view-only' request was issued, but this isn't directly supported at the protocol level for VMWare. The ConsoleComponent will do its best to make the console canvas view-only. Request:", isViewOnly);
871
905
  return Promise.resolve();
872
906
  }
873
- setPreserveAspectRatioOnScale(scaleToContainerSize) {
874
- return new Promise((resolve, reject) => {
875
- try {
876
- if (!this.wmksClient) {
877
- throw new Error("Couldn't resolve client; can't set option");
878
- }
879
- this.wmksClient.setOption("rescale", scaleToContainerSize);
880
- resolve();
881
- }
882
- catch (err) {
883
- reject(err);
884
- }
885
- });
886
- }
887
907
  dispose() {
888
908
  if (this.wmksClient) {
889
909
  this.wmksClient.destroy();
@@ -915,6 +935,8 @@ class VmWareConsoleClientService {
915
935
  }
916
936
  });
917
937
  }
938
+ // finally, update from user settings to ensure the behavior the user expects
939
+ this.updateFromUserSettings(this.userSettings.settings());
918
940
  }
919
941
  doPostDisconnectionConfig() {
920
942
  this.document.removeEventListener("fullscreenchange", this.handleWindowSizeChange.bind(this));
@@ -923,13 +945,21 @@ class VmWareConsoleClientService {
923
945
  handleWindowSizeChange() {
924
946
  this._needsCanvasSizeUpdate.next();
925
947
  }
948
+ updateFromUserSettings(settings) {
949
+ if (!this.wmksClient) {
950
+ return;
951
+ }
952
+ this.wmksClient.setOption("changeResolution", settings.console.attemptRemoteSessionResize);
953
+ this.wmksClient.setOption("rescale", settings.console.scaleToCanvasHostSize);
954
+ this.wmksClient.updateScreen();
955
+ }
926
956
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
927
957
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, providedIn: 'root' });
928
958
  }
929
959
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, decorators: [{
930
960
  type: Injectable,
931
961
  args: [{ providedIn: 'root' }]
932
- }] });
962
+ }], ctorParameters: () => [] });
933
963
 
934
964
  // ===BEGIN LICENSE===
935
965
  // Copyright 2025 Carnegie Mellon University. All rights reserved.
@@ -1186,11 +1216,13 @@ class ConsoleToolbarComponent {
1186
1216
  canvasRecorder = inject(CanvasRecorderService);
1187
1217
  clipboardService = inject(ClipboardService);
1188
1218
  config = inject(ConsoleForgeConfig);
1219
+ fullscreen = inject(FullScreenService);
1189
1220
  logger = inject(LoggerService);
1190
1221
  userSettings = inject(UserSettingsService);
1191
1222
  window = inject(WINDOW);
1192
1223
  // component state
1193
1224
  activeConsoleRecording = signal(undefined);
1225
+ isConnected = computed(() => this.consoleClient()?.connectionStatus() === "connected");
1194
1226
  isManualConsoleReconnectAvailable = computed(() => !this.config.disabledFeatures.manualConsoleReconnect && this.consoleClient()?.connectionStatus() !== "connecting");
1195
1227
  toolbarComponentContext;
1196
1228
  toolbarComponent = computed(() => this.customToolbarComponent() || this.config.toolbar.component);
@@ -1214,11 +1246,11 @@ class ConsoleToolbarComponent {
1214
1246
  networks: {
1215
1247
  config: this.consoleNetworkConfig,
1216
1248
  connectionRequested: this.handleNetworkConnectionRequest.bind(this),
1217
- disconnectRequested: () => this.networkDisconnectRequested.emit(),
1249
+ disconnectRequested: this.handleNetworkDisconnectionRequest.bind(this),
1218
1250
  },
1219
1251
  state: {
1220
1252
  activeConsoleRecording: computed(() => this.activeConsoleRecording()?.recording),
1221
- isConnected: computed(() => this.consoleClient() && this.consoleClient().connectionStatus() === "connected"),
1253
+ isConnected: this.isConnected,
1222
1254
  isFullscreenAvailable: inject(FullScreenService).isAvailable,
1223
1255
  isManualReconnectAvailable: this.isManualConsoleReconnectAvailable,
1224
1256
  isRecordingAvailable: computed(() => !!this.canvas.canvas()),
@@ -1226,6 +1258,18 @@ class ConsoleToolbarComponent {
1226
1258
  },
1227
1259
  userSettings: this.userSettings
1228
1260
  };
1261
+ // VNC seems to get mouse tracking weirdness in some configurations when exiting fullscreen mode, so work around for now
1262
+ // by requesting a reconnect when exiting FS
1263
+ effect(() => {
1264
+ const untrackedContext = untracked(() => ({
1265
+ isConnected: this.isConnected(),
1266
+ requireReconnectOnFullscreenExit: this.toolbarComponentContext.console.supportedFeatures().requireReconnectOnExitingFullscreen || false,
1267
+ }));
1268
+ const isFullscreenActive = this.fullscreen.isActive();
1269
+ if (untrackedContext.isConnected && untrackedContext.requireReconnectOnFullscreenExit && !isFullscreenActive) {
1270
+ this.toolbarComponentContext.console.sendReconnectRequest();
1271
+ }
1272
+ });
1229
1273
  }
1230
1274
  async handleCopyScreenshot() {
1231
1275
  if (!this.canvas.canvas()) {
@@ -1241,21 +1285,26 @@ class ConsoleToolbarComponent {
1241
1285
  }
1242
1286
  handleFullscreen() {
1243
1287
  this.toggleFullscreen.emit();
1244
- if (this.consoleClient()) {
1245
- this.consoleClient().handlePostFullscreenChange();
1246
- }
1247
1288
  return Promise.resolve();
1248
1289
  }
1249
1290
  async handleKeyboardInputSend(text) {
1250
1291
  await this.consoleClient().sendKeyboardInput(text);
1251
1292
  this.keyboardInputSent.emit(text);
1252
1293
  }
1253
- handleNetworkConnectionRequest(networkName) {
1254
- const availableNetworks = this.consoleNetworkConfig()?.available || [];
1255
- if (availableNetworks.indexOf(networkName) === -1) {
1256
- throw new Error(`Network ${networkName} is not available to this console.`);
1294
+ handleNetworkConnectionRequest(request) {
1295
+ const availableNetworks = this.consoleNetworkConfig()?.networks || [];
1296
+ if (availableNetworks.indexOf(request.network) === -1) {
1297
+ throw new Error(`Network "${request.network}" is not available to this console.`);
1257
1298
  }
1258
- this.networkConnectionRequested.emit(networkName);
1299
+ this.networkConnectionRequested.emit(request);
1300
+ }
1301
+ handleNetworkDisconnectionRequest(request) {
1302
+ if (request?.nic && this.consoleNetworkConfig()?.nics) {
1303
+ if (this.consoleNetworkConfig()?.nics.indexOf(request.nic) === -1) {
1304
+ throw new Error(`NIC ${request.nic} is not available to this console.`);
1305
+ }
1306
+ }
1307
+ this.networkDisconnectRequested.emit(request);
1259
1308
  }
1260
1309
  handleReconnectRequestSent() {
1261
1310
  this.logger.log(LogLevel.DEBUG, "Manual reconnect request from toolbar");
@@ -1430,14 +1479,12 @@ class ConsoleComponent {
1430
1479
  });
1431
1480
  userSettings = this.userSettingsService.settings;
1432
1481
  constructor() {
1433
- // we need this component to emit from outputs or call the client when signals change, so an effect
1434
- // is the recommended solution: https://github.com/angular/angular/issues/57208
1435
1482
  // when config is provided and autoconnect is on, attempt to automatically connect
1436
1483
  effect(() => {
1437
1484
  const autoConnect = untracked(() => this.autoConnect());
1438
1485
  const currentConfig = this.config();
1439
1486
  if (autoConnect && currentConfig) {
1440
- this.logger.log(LogLevel.DEBUG, "Autoconnect firing", currentConfig);
1487
+ this.logger.log(LogLevel.DEBUG, "Autoconnecting...", currentConfig);
1441
1488
  this.connect(currentConfig);
1442
1489
  }
1443
1490
  });
@@ -1461,7 +1508,7 @@ class ConsoleComponent {
1461
1508
  effect(() => {
1462
1509
  // all supported console clients inject a canvas into the doc. We provide it to the canvas service so it
1463
1510
  // can be consumed by other components (e.g. the ConsoleToolbarComponent and its implementations)
1464
- if (this.document && this.consoleClientConnectionStatus() === "connected") {
1511
+ if (this.consoleClientConnectionStatus() === "connected") {
1465
1512
  const canvas = this.resolveConsoleCanvas();
1466
1513
  if (canvas) {
1467
1514
  this.canvasService.setCanvas(canvas);
@@ -1471,16 +1518,6 @@ class ConsoleComponent {
1471
1518
  }
1472
1519
  }
1473
1520
  });
1474
- // fullscreen events (VNC requires reconnect after fullscreen goes negative because of mouse pointer problems)
1475
- effect(() => {
1476
- const currentConfig = untracked(() => this.config());
1477
- const isConnected = untracked(() => this.consoleClientConnectionStatus() === "connected");
1478
- const isFullscreen = this.fullscreen.isActive();
1479
- if (isConnected && !isFullscreen) {
1480
- console.log("FULLSCREEN STUFF");
1481
- this.reconnectRequest.emit(currentConfig);
1482
- }
1483
- });
1484
1521
  // input changes
1485
1522
  effect(() => {
1486
1523
  // read values - this effect WILL happen when these values change
@@ -1503,13 +1540,6 @@ class ConsoleComponent {
1503
1540
  });
1504
1541
  // output emitters
1505
1542
  effect(() => this.connectionStatusChanged.emit(this.consoleClientConnectionStatus()));
1506
- // settings changes
1507
- effect(() => {
1508
- const currentSettings = this.userSettingsService.settings();
1509
- if (this.consoleClient() && this.consoleClientConnectionStatus() === "connected") {
1510
- this.consoleClient().setPreserveAspectRatioOnScale(currentSettings.console.preserveAspectRatioOnScale);
1511
- }
1512
- });
1513
1543
  }
1514
1544
  async ngOnDestroy() {
1515
1545
  if (this.consoleClient()) {
@@ -1590,7 +1620,7 @@ class ConsoleComponent {
1590
1620
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleComponent, isStandalone: true, selector: "cf-console", inputs: { autoConnect: { classPropertyName: "autoConnect", publicName: "autoConnect", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, isViewOnly: { classPropertyName: "isViewOnly", publicName: "isViewOnly", isSignal: true, isRequired: false, transformFunction: null }, networkConfig: { classPropertyName: "networkConfig", publicName: "networkConfig", isSignal: true, isRequired: false, transformFunction: null }, toolbarComponent: { classPropertyName: "toolbarComponent", publicName: "toolbarComponent", isSignal: true, isRequired: false, transformFunction: null }, toolbarDisabled: { classPropertyName: "toolbarDisabled", publicName: "toolbarDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { connectionStatusChanged: "connectionStatusChanged", consoleClipboardUpdated: "consoleClipboardUpdated", consoleRecorded: "consoleRecorded", ctrlAltDelSent: "ctrlAltDelSent", localClipboardUpdated: "localClipboardUpdated", networkConnectionRequested: "networkConnectionRequested", networkDisconnectRequested: "networkDisconnectRequested", powerRequestSent: "powerRequestSent", reconnectRequest: "reconnectRequest", screenshotCopied: "screenshotCopied" }, providers: [
1591
1621
  // the console component has access to the canvas which is injected by
1592
1622
  CanvasService
1593
- ], viewQueries: [{ propertyName: "componentContainer", first: true, predicate: ["componentContainer"], descendants: true, isSignal: true }, { propertyName: "consoleHostElement", first: true, predicate: ["consoleHost"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div #componentContainer class=\"console-component flex\"\n [class.console-client-type-vnc]=\"consoleClient()?.clientType == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClient()?.clientType == 'vmware'\"\n [class.flex-column]=\"userSettings().toolbar.dockTo === 'top' || userSettings().toolbar.dockTo === 'bottom'\">\n\n @if (toolbarEnabled()) {\n <cf-console-toolbar\n [class.flex-order-1]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\"\n [consoleClient]=\"consoleClient()!\" [consoleNetworkConfig]=\"networkConfig()\" [isViewOnly]=\"isViewOnly()\"\n (canvasRecordingFinished)=\"consoleRecorded.emit($event)\"\n (canvasRecordingStarted)=\"handleConsoleRecordingStarted()\" [customToolbarComponent]=\"toolbarComponent()\"\n (ctrlAltDelSent)=\"handleCtrlAltDelSent()\" (networkConnectionRequested)=\"networkConnectionRequested.emit($event)\"\n (powerRequestSent)=\"powerRequestSent.emit($event)\"\n (networkDisconnectRequested)=\"networkDisconnectRequested.emit()\"\n (reconnectRequestSent)=\"handleReconnectRequest()\" (screenshotCopied)=\"handleScreenshotCopied($event)\"\n (toggleFullscreen)=\"handleFullscreen()\"></cf-console-toolbar>\n }\n\n <div class=\"console-host-container\" [style.background]=\"consoleHostBackgroundStyle\"\n [class.flex-order-0]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\">\n <cf-console-status [status]=\"consoleClient()?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\" [class.recording]=\"isRecording()\"\n [class.view-only]=\"isViewOnly()\">\n </div>\n </div>\n</div>\n", styles: [".console-component{max-width:100vw;max-height:100vh;width:100%;height:100%}cf-console-toolbar{display:block;flex:0 1 auto;max-height:100%;max-width:100%}cf-console-status{width:100%}:fullscreen{width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important}:fullscreen cf-console-toolbar{z-index:5}.console-host-container{align-items:center;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;max-height:100%;max-width:100%;justify-content:center}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.recording{outline:4px solid #ee402e}.flex{display:flex;flex-direction:row}.flex.flex-column{flex-direction:column}.flex-order-0{order:0}.flex-order-1{order:1}.console-component.console-client-type-vmware:not(:fullscreen) ::ng-deep canvas{aspect-ratio:16/9!important;max-height:100%!important;max-width:100%!important;position:unset!important}.console-component.console-client-type-vmware .console-host{display:flex;justify-content:center;aspect-ratio:16/9}.console-component.console-client-type-vmware .console-host.view-only ::ng-deep canvas{cursor:not-allowed;pointer-events:none!important}.console-component.console-client-type-vnc ::ng-deep canvas{height:100%!important;width:100%!important}\n"], dependencies: [{ kind: "component", type: ConsoleStatusComponent, selector: "cf-console-status", inputs: ["status"], outputs: ["reconnectRequest"] }, { kind: "component", type: ConsoleToolbarComponent, selector: "cf-console-toolbar", inputs: ["consoleClient", "consoleNetworkConfig", "customToolbarComponent", "isViewOnly"], outputs: ["canvasRecordingStarted", "canvasRecordingFinished", "ctrlAltDelSent", "keyboardInputSent", "networkConnectionRequested", "networkDisconnectRequested", "powerRequestSent", "reconnectRequestSent", "screenshotCopied", "toggleFullscreen"] }] });
1623
+ ], viewQueries: [{ propertyName: "componentContainer", first: true, predicate: ["componentContainer"], descendants: true, isSignal: true }, { propertyName: "consoleHostElement", first: true, predicate: ["consoleHost"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div #componentContainer class=\"console-component flex\"\n [class.console-client-type-vnc]=\"consoleClient()?.clientType == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClient()?.clientType == 'vmware'\"\n [class.flex-column]=\"userSettings().toolbar.dockTo === 'top' || userSettings().toolbar.dockTo === 'bottom'\">\n\n @if (toolbarEnabled()) {\n <cf-console-toolbar\n [class.flex-order-1]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\"\n [consoleClient]=\"consoleClient()!\" [consoleNetworkConfig]=\"networkConfig()\" [isViewOnly]=\"isViewOnly()\"\n (canvasRecordingFinished)=\"consoleRecorded.emit($event)\"\n (canvasRecordingStarted)=\"handleConsoleRecordingStarted()\" [customToolbarComponent]=\"toolbarComponent()\"\n (ctrlAltDelSent)=\"handleCtrlAltDelSent()\" (networkConnectionRequested)=\"networkConnectionRequested.emit($event)\"\n (powerRequestSent)=\"powerRequestSent.emit($event)\"\n (networkDisconnectRequested)=\"networkDisconnectRequested.emit($event)\"\n (reconnectRequestSent)=\"handleReconnectRequest()\" (screenshotCopied)=\"handleScreenshotCopied($event)\"\n (toggleFullscreen)=\"handleFullscreen()\"></cf-console-toolbar>\n }\n\n <div class=\"console-host-container\" [style.background]=\"consoleHostBackgroundStyle\"\n [class.flex-order-0]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\">\n <cf-console-status [status]=\"consoleClient()?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\" [class.recording]=\"isRecording()\"\n [class.view-only]=\"isViewOnly()\">\n </div>\n </div>\n</div>\n", styles: [".console-component{max-width:100vw;max-height:100vh;width:100%;height:100%}cf-console-toolbar{display:block;flex:0 1 auto;max-height:100%;max-width:100%}cf-console-status{width:100%}:fullscreen{width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important}:fullscreen cf-console-toolbar{z-index:5}.console-host-container{align-items:center;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;max-height:100%;max-width:100%;justify-content:center}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.recording{outline:4px solid #ee402e}.flex{display:flex;flex-direction:row}.flex.flex-column{flex-direction:column}.flex-order-0{order:0}.flex-order-1{order:1}.console-component.console-client-type-vmware:not(:fullscreen) ::ng-deep canvas{aspect-ratio:16/9!important;max-height:100%!important;max-width:100%!important;position:unset!important}.console-component.console-client-type-vmware .console-host{display:flex;justify-content:center;aspect-ratio:16/9}.console-component.console-client-type-vmware .console-host.view-only ::ng-deep canvas{cursor:not-allowed;pointer-events:none!important}\n"], dependencies: [{ kind: "component", type: ConsoleStatusComponent, selector: "cf-console-status", inputs: ["status"], outputs: ["reconnectRequest"] }, { kind: "component", type: ConsoleToolbarComponent, selector: "cf-console-toolbar", inputs: ["consoleClient", "consoleNetworkConfig", "customToolbarComponent", "isViewOnly"], outputs: ["canvasRecordingStarted", "canvasRecordingFinished", "ctrlAltDelSent", "keyboardInputSent", "networkConnectionRequested", "networkDisconnectRequested", "powerRequestSent", "reconnectRequestSent", "screenshotCopied", "toggleFullscreen"] }] });
1594
1624
  }
1595
1625
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleComponent, decorators: [{
1596
1626
  type: Component,
@@ -1600,7 +1630,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1600
1630
  ], providers: [
1601
1631
  // the console component has access to the canvas which is injected by
1602
1632
  CanvasService
1603
- ], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div #componentContainer class=\"console-component flex\"\n [class.console-client-type-vnc]=\"consoleClient()?.clientType == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClient()?.clientType == 'vmware'\"\n [class.flex-column]=\"userSettings().toolbar.dockTo === 'top' || userSettings().toolbar.dockTo === 'bottom'\">\n\n @if (toolbarEnabled()) {\n <cf-console-toolbar\n [class.flex-order-1]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\"\n [consoleClient]=\"consoleClient()!\" [consoleNetworkConfig]=\"networkConfig()\" [isViewOnly]=\"isViewOnly()\"\n (canvasRecordingFinished)=\"consoleRecorded.emit($event)\"\n (canvasRecordingStarted)=\"handleConsoleRecordingStarted()\" [customToolbarComponent]=\"toolbarComponent()\"\n (ctrlAltDelSent)=\"handleCtrlAltDelSent()\" (networkConnectionRequested)=\"networkConnectionRequested.emit($event)\"\n (powerRequestSent)=\"powerRequestSent.emit($event)\"\n (networkDisconnectRequested)=\"networkDisconnectRequested.emit()\"\n (reconnectRequestSent)=\"handleReconnectRequest()\" (screenshotCopied)=\"handleScreenshotCopied($event)\"\n (toggleFullscreen)=\"handleFullscreen()\"></cf-console-toolbar>\n }\n\n <div class=\"console-host-container\" [style.background]=\"consoleHostBackgroundStyle\"\n [class.flex-order-0]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\">\n <cf-console-status [status]=\"consoleClient()?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\" [class.recording]=\"isRecording()\"\n [class.view-only]=\"isViewOnly()\">\n </div>\n </div>\n</div>\n", styles: [".console-component{max-width:100vw;max-height:100vh;width:100%;height:100%}cf-console-toolbar{display:block;flex:0 1 auto;max-height:100%;max-width:100%}cf-console-status{width:100%}:fullscreen{width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important}:fullscreen cf-console-toolbar{z-index:5}.console-host-container{align-items:center;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;max-height:100%;max-width:100%;justify-content:center}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.recording{outline:4px solid #ee402e}.flex{display:flex;flex-direction:row}.flex.flex-column{flex-direction:column}.flex-order-0{order:0}.flex-order-1{order:1}.console-component.console-client-type-vmware:not(:fullscreen) ::ng-deep canvas{aspect-ratio:16/9!important;max-height:100%!important;max-width:100%!important;position:unset!important}.console-component.console-client-type-vmware .console-host{display:flex;justify-content:center;aspect-ratio:16/9}.console-component.console-client-type-vmware .console-host.view-only ::ng-deep canvas{cursor:not-allowed;pointer-events:none!important}.console-component.console-client-type-vnc ::ng-deep canvas{height:100%!important;width:100%!important}\n"] }]
1633
+ ], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div #componentContainer class=\"console-component flex\"\n [class.console-client-type-vnc]=\"consoleClient()?.clientType == 'vnc'\"\n [class.console-client-type-vmware]=\"consoleClient()?.clientType == 'vmware'\"\n [class.flex-column]=\"userSettings().toolbar.dockTo === 'top' || userSettings().toolbar.dockTo === 'bottom'\">\n\n @if (toolbarEnabled()) {\n <cf-console-toolbar\n [class.flex-order-1]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\"\n [consoleClient]=\"consoleClient()!\" [consoleNetworkConfig]=\"networkConfig()\" [isViewOnly]=\"isViewOnly()\"\n (canvasRecordingFinished)=\"consoleRecorded.emit($event)\"\n (canvasRecordingStarted)=\"handleConsoleRecordingStarted()\" [customToolbarComponent]=\"toolbarComponent()\"\n (ctrlAltDelSent)=\"handleCtrlAltDelSent()\" (networkConnectionRequested)=\"networkConnectionRequested.emit($event)\"\n (powerRequestSent)=\"powerRequestSent.emit($event)\"\n (networkDisconnectRequested)=\"networkDisconnectRequested.emit($event)\"\n (reconnectRequestSent)=\"handleReconnectRequest()\" (screenshotCopied)=\"handleScreenshotCopied($event)\"\n (toggleFullscreen)=\"handleFullscreen()\"></cf-console-toolbar>\n }\n\n <div class=\"console-host-container\" [style.background]=\"consoleHostBackgroundStyle\"\n [class.flex-order-0]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\">\n <cf-console-status [status]=\"consoleClient()?.connectionStatus()\"\n (reconnectRequest)=\"reconnectRequest.emit(this.config())\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\" [class.recording]=\"isRecording()\"\n [class.view-only]=\"isViewOnly()\">\n </div>\n </div>\n</div>\n", styles: [".console-component{max-width:100vw;max-height:100vh;width:100%;height:100%}cf-console-toolbar{display:block;flex:0 1 auto;max-height:100%;max-width:100%}cf-console-status{width:100%}:fullscreen{width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important}:fullscreen cf-console-toolbar{z-index:5}.console-host-container{align-items:center;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;max-height:100%;max-width:100%;justify-content:center}.console-host{max-width:100%;max-height:100%;width:100%;aspect-ratio:16/9;margin:0 auto;overflow:hidden}.console-host.recording{outline:4px solid #ee402e}.flex{display:flex;flex-direction:row}.flex.flex-column{flex-direction:column}.flex-order-0{order:0}.flex-order-1{order:1}.console-component.console-client-type-vmware:not(:fullscreen) ::ng-deep canvas{aspect-ratio:16/9!important;max-height:100%!important;max-width:100%!important;position:unset!important}.console-component.console-client-type-vmware .console-host{display:flex;justify-content:center;aspect-ratio:16/9}.console-component.console-client-type-vmware .console-host.view-only ::ng-deep canvas{cursor:not-allowed;pointer-events:none!important}\n"] }]
1604
1634
  }], ctorParameters: () => [] });
1605
1635
 
1606
1636
  class ConsoleTileComponent {