[cleanup] Remove three more obsolete view singletons.

1. Remove the `NodeConnectionsPanel` singleton.
2. Remove the `ChangesView` singleton together with the unused
   `DiffUILocation` and its revealer.
3. Remove the `IssuesPane` singleton and use the revealer in the
   Elements panel to avoid tight coupling.

Bug: chromium:1379221
Change-Id: I3fcae6aa8c740dd3ded01d01f6855e9aec021c7e
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5111179
Reviewed-by: Simon Zünd <[email protected]>
Commit-Queue: Benedikt Meurer <[email protected]>
Auto-Submit: Benedikt Meurer <[email protected]>
diff --git a/front_end/entrypoints/node_app/NodeConnectionsPanel.ts b/front_end/entrypoints/node_app/NodeConnectionsPanel.ts
index 777537190..87ff381 100644
--- a/front_end/entrypoints/node_app/NodeConnectionsPanel.ts
+++ b/front_end/entrypoints/node_app/NodeConnectionsPanel.ts
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import nodeConnectionsPanelStyles from './nodeConnectionsPanel.css.js';
 import type * as Common from '../../core/common/common.js';
 import * as Host from '../../core/host/host.js';
 import * as i18n from '../../core/i18n/i18n.js';
 import * as UI from '../../ui/legacy/legacy.js';
 
+import nodeConnectionsPanelStyles from './nodeConnectionsPanel.css.js';
+
 const UIStrings = {
   /**
    *@description Text in Node Connections Panel of the Sources panel when debugging a Node.js app
@@ -35,12 +36,10 @@
 const str_ = i18n.i18n.registerUIStrings('entrypoints/node_app/NodeConnectionsPanel.ts', UIStrings);
 const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
 
-let nodeConnectionsPanelInstance: NodeConnectionsPanel;
-
 export class NodeConnectionsPanel extends UI.Panel.Panel {
   #config!: Adb.Config;
   readonly #networkDiscoveryView: NodeConnectionsView;
-  private constructor() {
+  constructor() {
     super('node-connection');
 
     this.contentElement.classList.add('node-panel');
@@ -67,17 +66,6 @@
     this.#networkDiscoveryView.show(container);
   }
 
-  static instance(opts: {
-    forceNew: boolean|null,
-  } = {forceNew: null}): NodeConnectionsPanel {
-    const {forceNew} = opts;
-    if (!nodeConnectionsPanelInstance || forceNew) {
-      nodeConnectionsPanelInstance = new NodeConnectionsPanel();
-    }
-
-    return nodeConnectionsPanelInstance;
-  }
-
   #devicesDiscoveryConfigChanged({data: config}: Common.EventTarget.EventTargetEvent<Adb.Config>): void {
     this.#config = config;
     this.#networkDiscoveryView.discoveryConfigChanged(this.#config.networkDiscoveryConfig);
diff --git a/front_end/entrypoints/node_app/node_app.ts b/front_end/entrypoints/node_app/node_app.ts
index f86f347..e27e34a 100644
--- a/front_end/entrypoints/node_app/node_app.ts
+++ b/front_end/entrypoints/node_app/node_app.ts
@@ -56,7 +56,7 @@
   commandPrompt: i18nLazyString(UIStrings.showConnection),
   order: 0,
   async loadView() {
-    return NodeConnectionsPanel.instance();
+    return new NodeConnectionsPanel();
   },
   tags: [i18nLazyString(UIStrings.node)],
 });
diff --git a/front_end/models/workspace_diff/WorkspaceDiff.ts b/front_end/models/workspace_diff/WorkspaceDiff.ts
index eedcf07..81933db 100644
--- a/front_end/models/workspace_diff/WorkspaceDiff.ts
+++ b/front_end/models/workspace_diff/WorkspaceDiff.ts
@@ -315,11 +315,4 @@
   return _instance;
 }
 
-export class DiffUILocation {
-  uiSourceCode: Workspace.UISourceCode.UISourceCode;
-  constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
-    this.uiSourceCode = uiSourceCode;
-  }
-}
-
 export const UpdateTimeout = 200;
diff --git a/front_end/panels/changes/ChangesView.ts b/front_end/panels/changes/ChangesView.ts
index 4853eda..4b533e1 100644
--- a/front_end/panels/changes/ChangesView.ts
+++ b/front_end/panels/changes/ChangesView.ts
@@ -56,8 +56,6 @@
   return `${insertionText}, ${deletionText}`;
 }
 
-let changesViewInstance: ChangesView;
-
 export class ChangesView extends UI.Widget.VBox {
   private emptyWidget: UI.EmptyWidget.EmptyWidget;
   private readonly workspaceDiff: WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl;
@@ -112,15 +110,6 @@
     this.selectedUISourceCodeChanged();
   }
 
-  static instance(opts: {forceNew: boolean|null} = {forceNew: null}): ChangesView {
-    const {forceNew} = opts;
-    if (!changesViewInstance || forceNew) {
-      changesViewInstance = new ChangesView();
-    }
-
-    return changesViewInstance;
-  }
-
   private selectedUISourceCodeChanged(): void {
     this.revealUISourceCode(this.changesSidebar.selectedUISourceCode());
     UI.ActionRegistry.ActionRegistry.instance()
@@ -254,22 +243,19 @@
 }
 
 export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
-  handleAction(_context: UI.Context.Context, actionId: string): boolean {
+  handleAction(context: UI.Context.Context, actionId: string): boolean {
+    const changesView = context.flavor(ChangesView);
+    if (changesView === null) {
+      return false;
+    }
     switch (actionId) {
       case 'changes.revert':
-        ChangesView.instance().revert();
+        changesView.revert();
         return true;
       case 'changes.copy':
-        void ChangesView.instance().copy();
+        void changesView.copy();
         return true;
     }
     return false;
   }
 }
-
-export class DiffUILocationRevealer implements Common.Revealer.Revealer<WorkspaceDiff.WorkspaceDiff.DiffUILocation> {
-  async reveal(diffUILocation: WorkspaceDiff.WorkspaceDiff.DiffUILocation, omitFocus?: boolean): Promise<void> {
-    await UI.ViewManager.ViewManager.instance().showView('changes.changes');
-    ChangesView.instance().changesSidebar.selectUISourceCode(diffUILocation.uiSourceCode, omitFocus);
-  }
-}
diff --git a/front_end/panels/changes/changes-meta.ts b/front_end/panels/changes/changes-meta.ts
index ed734f2..e49693c 100644
--- a/front_end/panels/changes/changes-meta.ts
+++ b/front_end/panels/changes/changes-meta.ts
@@ -2,9 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import * as Common from '../../core/common/common.js';
 import * as i18n from '../../core/i18n/i18n.js';
-import * as WorkspaceDiff from '../../models/workspace_diff/workspace_diff.js';
 import * as UI from '../../ui/legacy/legacy.js';
 
 import type * as Changes from './changes.js';
@@ -54,7 +52,7 @@
   persistence: UI.ViewManager.ViewPersistence.CLOSEABLE,
   async loadView() {
     const Changes = await loadChangesModule();
-    return Changes.ChangesView.ChangesView.instance();
+    return new Changes.ChangesView.ChangesView();
   },
 });
 
@@ -85,16 +83,3 @@
     return maybeRetrieveContextTypes(Changes => [Changes.ChangesView.ChangesView]);
   },
 });
-
-Common.Revealer.registerRevealer({
-  contextTypes() {
-    return [
-      WorkspaceDiff.WorkspaceDiff.DiffUILocation,
-    ];
-  },
-  destination: Common.Revealer.RevealerDestination.CHANGES_DRAWER,
-  async loadRevealer() {
-    const Changes = await loadChangesModule();
-    return new Changes.ChangesView.DiffUILocationRevealer();
-  },
-});
diff --git a/front_end/panels/elements/ElementsTreeOutline.ts b/front_end/panels/elements/ElementsTreeOutline.ts
index 6864aca..61bade2 100644
--- a/front_end/panels/elements/ElementsTreeOutline.ts
+++ b/front_end/panels/elements/ElementsTreeOutline.ts
@@ -45,7 +45,6 @@
 import * as IssueCounter from '../../ui/components/issue_counter/issue_counter.js';
 import * as UI from '../../ui/legacy/legacy.js';
 import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
-import {IssuesPane} from '../issues/IssuesPane.js';
 
 import * as ElementsComponents from './components/components.js';
 import {ElementsPanel} from './ElementsPanel.js';
@@ -236,10 +235,7 @@
           box: hoveredNode.boxInWindow(),
           show: async(popover: UI.GlassPane.GlassPane): Promise<boolean> => {
             popover.setIgnoreLeftMargin(true);
-            const openIssueEvent = (): void => {
-              void UI.ViewManager.ViewManager.instance().showView('issues-pane');
-              void IssuesPane.instance().reveal(issue);
-            };
+            const openIssueEvent = (): Promise<void> => Common.Revealer.reveal(issue);
             viewIssueElement.addEventListener('click', () => openIssueEvent());
             issueKindIcon.addEventListener('click', () => openIssueEvent());
             popover.contentElement.appendChild(element);
diff --git a/front_end/panels/issues/IssuesPane.ts b/front_end/panels/issues/IssuesPane.ts
index 38b8c10..8b35514 100644
--- a/front_end/panels/issues/IssuesPane.ts
+++ b/front_end/panels/issues/IssuesPane.ts
@@ -168,8 +168,6 @@
   return Common.Settings.Settings.instance().createSetting('groupIssuesByCategory', false);
 }
 
-let issuesPaneInstance: IssuesPane;
-
 export class IssuesPane extends UI.Widget.VBox {
   #categoryViews: Map<IssuesManager.Issue.IssueCategory, IssueCategoryView>;
   #issueViews: Map<AggregationKey, IssueView>;
@@ -182,7 +180,7 @@
   #aggregator: IssueAggregator;
   #issueViewUpdatePromise: Promise<void> = Promise.resolve();
 
-  private constructor() {
+  constructor() {
     super(true);
 
     this.element.setAttribute('jslog', `${VisualLogging.panel().context('issues')}`);
@@ -219,15 +217,6 @@
         IssuesManager.IssuesManager.Events.IssuesCountUpdated, this.#updateCounts, this);
   }
 
-  static instance(opts: {forceNew: boolean|null} = {forceNew: null}): IssuesPane {
-    const {forceNew} = opts;
-    if (!issuesPaneInstance || forceNew) {
-      issuesPaneInstance = new IssuesPane();
-    }
-
-    return issuesPaneInstance;
-  }
-
   override elementsToRestoreScrollPositionsFor(): Element[] {
     return [this.#issuesTree.element];
   }
diff --git a/front_end/panels/issues/issues-meta.ts b/front_end/panels/issues/issues-meta.ts
index 8b25c0b..6b7f6d8 100644
--- a/front_end/panels/issues/issues-meta.ts
+++ b/front_end/panels/issues/issues-meta.ts
@@ -39,7 +39,7 @@
   persistence: UI.ViewManager.ViewPersistence.CLOSEABLE,
   async loadView() {
     const Issues = await loadIssuesModule();
-    return Issues.IssuesPane.IssuesPane.instance();
+    return new Issues.IssuesPane.IssuesPane();
   },
 });