Skip to content

Commit 0d412b5

Browse files
committed
add navigation to visible panels from infobar
1 parent 2f7a878 commit 0d412b5

9 files changed

+183
-85
lines changed

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "1.0.0",
2+
"version": "1.0.1",
33
"name": "API Monitor",
44
"manifest_version": 3,
55
"description": "Monitor browser API usage",

public/global.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
:root {
2+
--header-height: 20px;
3+
24
--bg: rgb(255 255 255);
35
--bg-invert: rgb(10% 10% 10% / 70%);
46
--bg-table-even: rgb(30% 30% 30% / 10%);
@@ -107,6 +109,21 @@ th,
107109
width: 100%;
108110
}
109111

112+
.divider {
113+
width: 1px;
114+
height: var(--header-height);
115+
background-color: var(--border);
116+
margin: 0 0.4rem;
117+
}
118+
.divider.-anchor-left {
119+
background-color: transparent;
120+
margin-left: 0;
121+
}
122+
.divider.-anchor-right {
123+
background-color: transparent;
124+
margin-right: 0;
125+
}
126+
110127
.icon {
111128
display: inline-block;
112129
width: 1rem;

src/api-monitor-cs-isolated.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ runtimePost({ msg: 'content-script-loaded' });
1414
getSettings().then((settings) => {
1515
windowPost({ msg: 'settings', settings: settings });
1616

17-
onSettingsChange((change) => {
18-
windowPost({ msg: 'settings', settings: change.newValue });
17+
onSettingsChange((newValue) => {
18+
windowPost({ msg: 'settings', settings: newValue });
1919
});
2020
});

src/api-monitor-cs-main.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,15 @@ import {
1010
meetMedia,
1111
type TMediaTelemetry,
1212
} from './api/mediaMonitor.ts';
13-
import {
14-
Wrapper,
15-
type TOnlineTimerMetrics,
16-
type TTimerHistory,
17-
type TEvalHistory,
18-
ETimeType,
19-
} from './api/wrappers.ts';
13+
import { Wrapper, ETimeType, type TWrapperMetrics } from './api/wrappers.ts';
2014
import {
2115
DEFAULT_SETTINGS,
2216
panelsArrayToVisibilityMap,
2317
} from './api/settings.ts';
2418

2519
export interface TMetrics {
2620
mediaMetrics: TMediaTelemetry;
27-
wrapperMetrics: {
28-
onlineTimeouts: TOnlineTimerMetrics[];
29-
onlineIntervals: TOnlineTimerMetrics[];
30-
setTimeoutHistory: TTimerHistory[];
31-
clearTimeoutHistory: TTimerHistory[];
32-
setIntervalHistory: TTimerHistory[];
33-
clearIntervalHistory: TTimerHistory[];
34-
evalHistory: TEvalHistory[];
35-
};
21+
wrapperMetrics: TWrapperMetrics;
3622
callCounter: {
3723
setTimeout: number;
3824
clearTimeout: number;

src/api/communication.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import { TMetrics } from '@/api-monitor-cs-main.ts';
1414
import { APPLICATION_NAME, ERRORS_IGNORED } from './const.ts';
1515
import type { ETimeType } from './wrappers.ts';
16-
import { DEFAULT_SETTINGS } from './settings.ts';
16+
import { type TSettings } from './settings.ts';
1717

1818
export function portPost(payload: TMsgOptions) {
1919
const port = chrome.tabs.connect(chrome.devtools.inspectedWindow.tabId, {
@@ -115,7 +115,7 @@ export interface TMsgTelemetry {
115115
}
116116
export interface TMsgSettings {
117117
msg: 'settings';
118-
settings: typeof DEFAULT_SETTINGS;
118+
settings: TSettings;
119119
}
120120
export type TMsgOptions =
121121
| TMsgTelemetry

src/api/settings.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export type TSettingsPanel = {
3131
visible: boolean;
3232
};
3333

34+
export type TSettings = typeof DEFAULT_SETTINGS;
3435
export type TSettingsProperty = Partial<typeof DEFAULT_SETTINGS>;
3536

3637
const SETTINGS_VERSION = '1.0.0';
@@ -87,9 +88,12 @@ export async function setSettings(value: TSettingsProperty) {
8788
}
8889

8990
export function onSettingsChange(
90-
callback: (change: chrome.storage.StorageChange) => void
91+
callback: (newValue: TSettings, oldValue: TSettings) => void
9192
) {
9293
chrome.storage.local.onChanged.addListener((change) => {
93-
callback(change[SETTINGS_VERSION]);
94+
callback(
95+
change[SETTINGS_VERSION].newValue,
96+
change[SETTINGS_VERSION].oldValue
97+
);
9498
});
9599
}

src/api/wrappers.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ export type TEvalHistory = {
4747
code: any;
4848
usesLocalScope: boolean;
4949
};
50+
export type TWrapperMetrics = {
51+
onlineTimers: number;
52+
onlineTimeouts: TOnlineTimerMetrics[];
53+
onlineIntervals: TOnlineTimerMetrics[];
54+
setTimeoutHistory: TTimerHistory[];
55+
clearTimeoutHistory: TTimerHistory[];
56+
setIntervalHistory: TTimerHistory[];
57+
clearIntervalHistory: TTimerHistory[];
58+
evalHistory: TEvalHistory[];
59+
};
5060

5161
type TOnlineTimers = Map<number, TOnlineTimerMetrics>;
5262

@@ -282,10 +292,11 @@ export class Wrapper {
282292
}
283293
}
284294

285-
collectWrapperMetrics(panels: TPanelVisibilityMap) {
295+
collectWrapperMetrics(panels: TPanelVisibilityMap): TWrapperMetrics {
286296
const timeouts: TOnlineTimerMetrics[] = [];
287297
const intervals: TOnlineTimerMetrics[] = [];
288298
const rv = {
299+
onlineTimers: this.onlineTimers.size,
289300
onlineTimeouts: timeouts,
290301
onlineIntervals: intervals,
291302
setTimeoutHistory: panels.setTimeoutHistory ? this.setTimeoutHistory : [],

src/view/App.svelte

Lines changed: 2 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import Version from './components/Version.svelte';
1111
import { onMount } from 'svelte';
1212
import TogglePanels from './components/TogglePanels.svelte';
13+
import InfoBar from './components/InfoBar.svelte';
1314
1415
let fpsValue = 0;
1516
const fps = new Fps((value) => (fpsValue = value)).start();
@@ -69,44 +70,7 @@
6970
<span class="icon -clear" />
7071
</button>
7172

72-
<div class="infobar">
73-
{#if msg}
74-
<div class="divider -anchor-left" />
75-
<div>
76-
<strong>eval</strong>: <Variable bind:value={msg.callCounter.eval} />
77-
</div>
78-
<div class="divider" />
79-
<div>
80-
<strong>setTimeout</strong>: <Variable
81-
bind:value={msg.callCounter.setTimeout}
82-
/>
83-
</div>
84-
<div class="divider" />
85-
<div>
86-
<strong>clearTimeout</strong>: <Variable
87-
bind:value={msg.callCounter.clearTimeout}
88-
/>
89-
</div>
90-
<div class="divider" />
91-
<div>
92-
<strong>setInterval</strong>: <Variable
93-
bind:value={msg.callCounter.setInterval}
94-
/>
95-
</div>
96-
<div class="divider" />
97-
<div>
98-
<strong>clearInterval</strong>: <Variable
99-
bind:value={msg.callCounter.clearInterval}
100-
/>
101-
</div>
102-
<div class="divider" />
103-
<div>
104-
<strong>Media</strong>:
105-
<Variable bind:value={msg.mediaMetrics.total} />
106-
</div>
107-
<div class="divider" />
108-
{/if}
109-
</div>
73+
<InfoBar bind:msg />
11074

11175
{#if msg && !paused}
11276
<div class="divider" />
@@ -143,39 +107,16 @@
143107

144108
<style lang="scss">
145109
.root {
146-
--header-height: 20px;
147110
display: flex;
148111
flex-direction: column;
149112
height: 100%;
150113
151-
.divider {
152-
width: 1px;
153-
height: var(--header-height);
154-
background-color: var(--border);
155-
margin: 0 0.4rem;
156-
157-
&.-anchor-left {
158-
background-color: transparent;
159-
margin-left: 0;
160-
}
161-
&.-anchor-right {
162-
background-color: transparent;
163-
margin-right: 0;
164-
}
165-
}
166-
167114
header {
168115
display: flex;
169116
align-items: center;
170117
height: var(--header-height);
171118
border-top: 1px solid var(--border);
172119
border-bottom: 1px solid var(--border);
173-
174-
.infobar {
175-
display: flex;
176-
align-items: center;
177-
flex-grow: 1;
178-
}
179120
}
180121
main {
181122
overflow-y: scroll;

src/view/components/InfoBar.svelte

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<script lang="ts">
2+
import { type TMetrics } from '@/api-monitor-cs-main.ts';
3+
import Variable from './Variable.svelte';
4+
import {
5+
getSettings,
6+
onSettingsChange,
7+
panelsArrayToVisibilityMap,
8+
type TPanelVisibilityMap,
9+
} from '@/api/settings.ts';
10+
11+
export let msg: TMetrics;
12+
13+
let panels: TPanelVisibilityMap;
14+
15+
getSettings().then((settings) => {
16+
panels = panelsArrayToVisibilityMap(settings.panels);
17+
18+
onSettingsChange((newValue) => {
19+
panels = panelsArrayToVisibilityMap(newValue.panels);
20+
});
21+
});
22+
23+
function scrollTo(e: MouseEvent, tableCaption: string) {
24+
e.preventDefault();
25+
const el = document.evaluate(
26+
`//caption[${tableCaption
27+
.split('|')
28+
.map((caption) => `contains(.,'${caption}')`)
29+
.join(' or ')}]`,
30+
document,
31+
null,
32+
XPathResult.FIRST_ORDERED_NODE_TYPE,
33+
null
34+
).singleNodeValue;
35+
36+
if (el instanceof HTMLElement) {
37+
el.scrollIntoView({
38+
behavior: 'smooth',
39+
block: 'start',
40+
inline: 'nearest',
41+
});
42+
}
43+
}
44+
</script>
45+
46+
<div class="infobar">
47+
{#if msg}
48+
<div class="divider -anchor-left" />
49+
<a
50+
href="void(0)"
51+
class:panel-enabled={panels.eval && msg.callCounter.eval}
52+
on:click={(e) => scrollTo(e, 'Eval Usages')}
53+
>
54+
<strong>eval</strong>: <Variable bind:value={msg.callCounter.eval} />
55+
</a>
56+
<div class="divider" />
57+
<a
58+
href="void(0)"
59+
class:panel-enabled={panels.activeTimers &&
60+
msg.wrapperMetrics.onlineTimers}
61+
on:click={(e) => scrollTo(e, 'Active')}
62+
>
63+
<strong>Active Timers</strong>: <Variable
64+
bind:value={msg.wrapperMetrics.onlineTimers}
65+
/>
66+
</a>
67+
<div class="divider" />
68+
<a
69+
href="void(0)"
70+
class:panel-enabled={panels.setTimeoutHistory &&
71+
msg.callCounter.setTimeout}
72+
on:click={(e) => scrollTo(e, 'setTimeout History')}
73+
>
74+
<strong>setTimeout</strong>: <Variable
75+
bind:value={msg.callCounter.setTimeout}
76+
/>
77+
</a>
78+
<div class="divider" />
79+
<a
80+
href="void(0)"
81+
class:panel-enabled={panels.clearTimeoutHistory &&
82+
msg.callCounter.clearTimeout}
83+
on:click={(e) => scrollTo(e, 'clearTimeout History')}
84+
>
85+
<strong>clearTimeout</strong>: <Variable
86+
bind:value={msg.callCounter.clearTimeout}
87+
/>
88+
</a>
89+
<div class="divider" />
90+
<a
91+
href="void(0)"
92+
class:panel-enabled={panels.setIntervalHistory &&
93+
msg.callCounter.setInterval}
94+
on:click={(e) => scrollTo(e, 'setInterval History')}
95+
>
96+
<strong>setInterval</strong>: <Variable
97+
bind:value={msg.callCounter.setInterval}
98+
/>
99+
</a>
100+
<div class="divider" />
101+
<a
102+
href="void(0)"
103+
class:panel-enabled={panels.clearIntervalHistory &&
104+
msg.callCounter.clearInterval}
105+
on:click={(e) => scrollTo(e, 'clearInterval History')}
106+
>
107+
<strong>clearInterval</strong>: <Variable
108+
bind:value={msg.callCounter.clearInterval}
109+
/>
110+
</a>
111+
<div class="divider" />
112+
<a
113+
href="void(0)"
114+
class:panel-enabled={panels.media && msg.mediaMetrics.total}
115+
on:click={(e) => scrollTo(e, 'Video|Audio')}
116+
>
117+
<strong>Media</strong>:
118+
<Variable bind:value={msg.mediaMetrics.total} />
119+
</a>
120+
<div class="divider" />
121+
{/if}
122+
</div>
123+
124+
<style lang="scss">
125+
.infobar {
126+
display: flex;
127+
align-items: center;
128+
flex-grow: 1;
129+
}
130+
131+
a {
132+
pointer-events: none;
133+
134+
&.panel-enabled {
135+
pointer-events: all;
136+
color: var(--text);
137+
}
138+
}
139+
</style>

0 commit comments

Comments
 (0)