summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/src/selectors/tabs.js
blob: 822bb7f49ae09df3a3bdb8d507ac07a985e9ab2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */

import { createSelector } from "devtools/client/shared/vendor/reselect";
import { getPrettySourceURL } from "../utils/source";

import { getSpecificSourceByURL } from "./sources";
import { isSimilarTab } from "../utils/tabs";

export const getTabs = state => state.tabs.tabs;

// Return the list of tabs which relates to an active source
export const getSourceTabs = createSelector(getTabs, tabs =>
  tabs.filter(tab => tab.source)
);

export const getSourcesForTabs = createSelector(getSourceTabs, sourceTabs => {
  return sourceTabs.map(tab => tab.source);
});

export function tabExists(state, sourceId) {
  return !!getSourceTabs(state).find(tab => tab.source.id == sourceId);
}

export function hasPrettyTab(state, source) {
  const prettyUrl = getPrettySourceURL(source.url);
  return getTabs(state).some(tab => tab.url === prettyUrl);
}

/**
 * Gets the next tab to select when a tab closes. Heuristics:
 * 1. if the selected tab is available, it remains selected
 * 2. if it is gone, the next available tab to the left should be active
 * 3. if the first tab is active and closed, select the second tab
 */
export function getNewSelectedSource(state, tabList) {
  const { selectedLocation } = state.sources;
  const availableTabs = getTabs(state);
  if (!selectedLocation) {
    return null;
  }

  const selectedSource = selectedLocation.source;
  if (!selectedSource) {
    return null;
  }

  const matchingTab = availableTabs.find(tab =>
    isSimilarTab(tab, selectedSource.url, selectedSource.isOriginal)
  );

  if (matchingTab) {
    const specificSelectedSource = getSpecificSourceByURL(
      state,
      selectedSource.url,
      selectedSource.isOriginal
    );

    if (specificSelectedSource) {
      return specificSelectedSource;
    }

    return null;
  }

  const tabUrls = tabList.map(tab => tab.url);
  const leftNeighborIndex = Math.max(
    tabUrls.indexOf(selectedSource.url) - 1,
    0
  );
  const lastAvailbleTabIndex = availableTabs.length - 1;
  const newSelectedTabIndex = Math.min(leftNeighborIndex, lastAvailbleTabIndex);
  const availableTab = availableTabs[newSelectedTabIndex];

  if (availableTab) {
    const tabSource = getSpecificSourceByURL(
      state,
      availableTab.url,
      availableTab.isOriginal
    );

    if (tabSource) {
      return tabSource;
    }
  }

  return null;
}