Skip to content

Commit 9635bd7

Browse files
authored
ntp: privacy stats ship review feedback (#1406)
1 parent bbdf594 commit 9635bd7

File tree

9 files changed

+64
-29
lines changed

9 files changed

+64
-29
lines changed

special-pages/pages/new-tab/app/customizer/integration-tests/customizer.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { test, expect } from '@playwright/test';
1+
import { expect, test } from '@playwright/test';
22
import { NewtabPage } from '../../../integration-tests/new-tab.page.js';
33
import { CustomizerPage } from './customizer.page.js';
44

@@ -255,7 +255,7 @@ test.describe('newtab customizer', () => {
255255
await ntp.reducedMotion();
256256
await ntp.openPage({ additional: { customizerDrawer: 'enabled', theme: 'light' } });
257257
await cp.opensCustomizer();
258-
await cp.hidesSection('Tracking Activity');
258+
await cp.hidesSection('Protection Stats');
259259
});
260260
test('opening settings', async ({ page }, workerInfo) => {
261261
const ntp = NewtabPage.create(page, workerInfo);

special-pages/pages/new-tab/app/privacy-stats/components/PrivacyStats.examples.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { h } from 'preact';
2-
import { noop } from '../../utils.js';
32
import { PrivacyStatsMockProvider } from '../mocks/PrivacyStatsMockProvider.js';
4-
import { PrivacyStatsConsumer, PrivacyStatsBody, Heading } from './PrivacyStats.js';
3+
import { PrivacyStatsConsumer, PrivacyStatsBody } from './PrivacyStats.js';
54
import { stats } from '../mocks/stats.js';
65

76
/** @type {Record<string, {factory: () => import("preact").ComponentChild}>} */
@@ -45,16 +44,6 @@ export const privacyStatsExamples = {
4544
'stats.list': {
4645
factory: () => <PrivacyStatsBody trackerCompanies={stats.few.trackerCompanies} listAttrs={{ id: 'example-stats.list' }} />,
4746
},
48-
'stats.heading': {
49-
factory: () => (
50-
<Heading trackerCompanies={stats.few.trackerCompanies} expansion={'expanded'} onToggle={noop('stats.heading onToggle')} />
51-
),
52-
},
53-
'stats.heading.none': {
54-
factory: () => (
55-
<Heading trackerCompanies={stats.none.trackerCompanies} expansion={'expanded'} onToggle={noop('stats.heading onToggle')} />
56-
),
57-
},
5847
};
5948

6049
export const otherPrivacyStatsExamples = {

special-pages/pages/new-tab/app/privacy-stats/components/PrivacyStats.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Fragment, h } from 'preact';
22
import cn from 'classnames';
33
import styles from './PrivacyStats.module.css';
44
import { useMessaging, useTypedTranslationWith } from '../../types.js';
5-
import { useContext, useState, useId, useCallback } from 'preact/hooks';
5+
import { useContext, useState, useId, useCallback, useMemo } from 'preact/hooks';
66
import { PrivacyStatsContext, PrivacyStatsProvider } from '../PrivacyStatsProvider.js';
77
import { useVisibility } from '../../widget-list/widget-config.provider.js';
88
import { viewTransition } from '../../utils.js';
@@ -60,7 +60,18 @@ function WithViewTransitions({ expansion, data, toggle }) {
6060
*/
6161
function PrivacyStatsConfigured({ parentRef, expansion, data, toggle }) {
6262
const expanded = expansion === 'expanded';
63-
const someCompanies = data.trackerCompanies.length > 0;
63+
64+
const { hasNamedCompanies, recent } = useMemo(() => {
65+
let recent = 0;
66+
let hasNamedCompanies = false;
67+
for (let i = 0; i < data.trackerCompanies.length; i++) {
68+
recent += data.trackerCompanies[i].count;
69+
if (!hasNamedCompanies && data.trackerCompanies[i].displayName !== DDG_STATS_OTHER_COMPANY_IDENTIFIER) {
70+
hasNamedCompanies = true;
71+
}
72+
}
73+
return { hasNamedCompanies, recent };
74+
}, [data.trackerCompanies]);
6475

6576
// see: https://www.w3.org/WAI/ARIA/apg/patterns/accordion/examples/accordion/
6677
const WIDGET_ID = useId();
@@ -69,30 +80,31 @@ function PrivacyStatsConfigured({ parentRef, expansion, data, toggle }) {
6980
return (
7081
<div class={styles.root} ref={parentRef}>
7182
<Heading
72-
trackerCompanies={data.trackerCompanies}
83+
recent={recent}
7384
onToggle={toggle}
7485
expansion={expansion}
86+
canExpand={hasNamedCompanies}
7587
buttonAttrs={{
7688
'aria-controls': WIDGET_ID,
7789
id: TOGGLE_ID,
7890
}}
7991
/>
80-
{expanded && someCompanies && <PrivacyStatsBody trackerCompanies={data.trackerCompanies} listAttrs={{ id: WIDGET_ID }} />}
92+
{hasNamedCompanies && expanded && <PrivacyStatsBody trackerCompanies={data.trackerCompanies} listAttrs={{ id: WIDGET_ID }} />}
8193
</div>
8294
);
8395
}
8496

8597
/**
8698
* @param {object} props
8799
* @param {Expansion} props.expansion
88-
* @param {TrackerCompany[]} props.trackerCompanies
100+
* @param {number} props.recent
101+
* @param {boolean} props.canExpand
89102
* @param {() => void} props.onToggle
90103
* @param {import("preact").ComponentProps<'button'>} [props.buttonAttrs]
91104
*/
92-
export function Heading({ expansion, trackerCompanies, onToggle, buttonAttrs = {} }) {
105+
export function Heading({ expansion, canExpand, recent, onToggle, buttonAttrs = {} }) {
93106
const { t } = useTypedTranslationWith(/** @type {enStrings} */ ({}));
94107
const [formatter] = useState(() => new Intl.NumberFormat());
95-
const recent = trackerCompanies.reduce((sum, item) => sum + item.count, 0);
96108

97109
const none = recent === 0;
98110
const some = recent > 0;
@@ -106,7 +118,7 @@ export function Heading({ expansion, trackerCompanies, onToggle, buttonAttrs = {
106118
</span>
107119
{none && <h2 className={styles.title}>{t('stats_noRecent')}</h2>}
108120
{some && <h2 className={styles.title}>{alltimeTitle}</h2>}
109-
{recent > 0 && (
121+
{recent > 0 && canExpand && (
110122
<span className={styles.widgetExpander}>
111123
<ShowHideButton
112124
buttonAttrs={{

special-pages/pages/new-tab/app/privacy-stats/components/PrivacyStats.module.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@
189189
.name {
190190
font-size: var(--title-3-em-font-size);
191191
font-weight: var(--title-3-em-font-weight);
192+
line-height: var(--title-3-em-line-height);
192193
text-overflow: ellipsis;
193194
display: block;
194195
overflow: hidden;

special-pages/pages/new-tab/app/privacy-stats/integration-tests/privacy-stats.page.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ export class PrivacyStatsPage {
4444
expect(await rows.count()).toBe(count);
4545
}
4646

47+
/**
48+
* @param {string} heading
49+
*/
50+
async hasHeading(heading) {
51+
await expect(this.context().getByRole('heading')).toContainText(heading);
52+
}
53+
4754
async showMoreSecondary() {
4855
await this.context().getByLabel('Show More', { exact: true }).click();
4956
}

special-pages/pages/new-tab/app/privacy-stats/integration-tests/privacy-stats.spec.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ test.describe('newtab privacy stats', () => {
7575
const ntp = NewtabPage.create(page, workerInfo);
7676
await ntp.reducedMotion();
7777
await ntp.openPage({ additional: { stats: 'none' } });
78-
await page.getByText('No recent tracking activity').waitFor();
78+
await page.getByText('Tracking protections active').waitFor();
7979
await expect(page.getByLabel('Hide recent activity')).not.toBeVisible();
8080
await expect(page.getByLabel('Show recent activity')).not.toBeVisible();
8181
},
@@ -145,4 +145,21 @@ test.describe('newtab privacy stats', () => {
145145
await psp.hasRows(2);
146146
},
147147
);
148+
test(
149+
'when all trackers are not within the top 100 companies',
150+
{
151+
annotation: {
152+
type: 'issue',
153+
description: 'https://app.asana.com/0/1201141132935289/1209123210947322/f',
154+
},
155+
},
156+
async ({ page }, workerInfo) => {
157+
const ntp = NewtabPage.create(page, workerInfo);
158+
const psp = new PrivacyStatsPage(page, ntp);
159+
await ntp.reducedMotion();
160+
await ntp.openPage({ additional: { stats: 'onlyother' } });
161+
await psp.hasRows(0);
162+
await psp.hasHeading('2 tracking attempts blocked');
163+
},
164+
);
148165
});

special-pages/pages/new-tab/app/privacy-stats/mocks/stats.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ export const stats = {
4747
totalCount: 0,
4848
trackerCompanies: [],
4949
},
50+
onlyother: {
51+
totalCount: 2,
52+
trackerCompanies: [
53+
{
54+
displayName: DDG_STATS_OTHER_COMPANY_IDENTIFIER,
55+
count: 2,
56+
},
57+
],
58+
},
5059
willUpdate: {
5160
totalCount: 481_113,
5261
trackerCompanies: [

special-pages/pages/new-tab/app/privacy-stats/strings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
"note": "Used as a label in a customization menu"
55
},
66
"stats_menuTitle_v2": {
7-
"title": "Tracking Activity",
7+
"title": "Protection Stats",
88
"note": "Used as a label in a customization menu"
99
},
1010
"stats_noActivity": {
11-
"title": "Blocked tracking attempts will appear here. Keep browsing to see how many we block.",
11+
"title": "DuckDuckGo blocks tracking attempts as you browse. Visit a few sites to see how many we block!",
1212
"note": "Placeholder for when we cannot report any blocked trackers yet"
1313
},
1414
"stats_noRecent": {
15-
"title": "No recent tracking activity",
15+
"title": "Tracking protections active",
1616
"note": "Placeholder to indicate that no tracking activity was blocked in the last 7 days"
1717
},
1818
"stats_countBlockedSingular": {

special-pages/pages/new-tab/public/locales/en/new-tab.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,15 @@
4646
"note": "Used as a label in a customization menu"
4747
},
4848
"stats_menuTitle_v2": {
49-
"title": "Tracking Activity",
49+
"title": "Protection Stats",
5050
"note": "Used as a label in a customization menu"
5151
},
5252
"stats_noActivity": {
53-
"title": "Blocked tracking attempts will appear here. Keep browsing to see how many we block.",
53+
"title": "DuckDuckGo blocks tracking attempts as you browse. Visit a few sites to see how many we block!",
5454
"note": "Placeholder for when we cannot report any blocked trackers yet"
5555
},
5656
"stats_noRecent": {
57-
"title": "No recent tracking activity",
57+
"title": "Tracking protections active",
5858
"note": "Placeholder to indicate that no tracking activity was blocked in the last 7 days"
5959
},
6060
"stats_countBlockedSingular": {

0 commit comments

Comments
 (0)