Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ntp: support multiple release-note lists #1385

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { UpdateNotificationProvider } from '../update-notification/UpdateNotific

export function factory() {
return (
<UpdateNotificationProvider data-entry-point="updateNotification">
<UpdateNotificationConsumer />
</UpdateNotificationProvider>
<div data-entry-point="updateNotification">
<UpdateNotificationProvider>
<UpdateNotificationConsumer />
</UpdateNotificationProvider>
</div>
);
}
10 changes: 5 additions & 5 deletions special-pages/pages/new-tab/app/mock-transport.js
Original file line number Diff line number Diff line change
Expand Up @@ -490,11 +490,11 @@ export function mockTransport() {
let updateNotification = { content: null };
const isDelayed = url.searchParams.has('update-notification-delay');

if (!isDelayed && url.searchParams.get('update-notification') === 'empty') {
updateNotification = updateNotificationExamples.empty;
}
if (!isDelayed && url.searchParams.get('update-notification') === 'populated') {
updateNotification = updateNotificationExamples.populated;
if (!isDelayed && url.searchParams.has('update-notification')) {
const value = url.searchParams.get('update-notification');
if (value && value in updateNotificationExamples) {
updateNotification = updateNotificationExamples[value];
}
}

/** @type {import('../types/new-tab.ts').InitialSetupResponse} */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { h } from 'preact';
import { Fragment, h } from 'preact';
import cn from 'classnames';
import styles from './UpdateNotification.module.css';
import { useContext, useId, useRef } from 'preact/hooks';
Expand All @@ -25,6 +25,11 @@ export function UpdateNotification({ notes, dismiss, version }) {
);
}

/**
* @param {object} props
* @param {string[]} props.notes
* @param {string} props.version
*/
export function WithNotes({ notes, version }) {
const id = useId();
const ref = useRef(/** @type {HTMLDetailsElement|null} */ (null));
Expand All @@ -45,27 +50,46 @@ export function WithNotes({ notes, version }) {
}}
/>
);
/** @type {{title: string, notes:string[]}[]} */
const chunks = [{ title: '', notes: [] }];
let index = 0;

for (const note of notes) {
const trimmed = note.trim();
if (!trimmed) continue;
if (trimmed.startsWith('•')) {
/**
* Note: Doing this here as a very specific 'view' concern
* Note: using the `if` + `.slice` to avoid regex
* Note: `.slice` is safe on `•` because it is a single Unicode character
* and is represented by a single UTF-16 code unit.
*/
const bullet = trimmed.slice(1).trim();
chunks[index].notes.push(bullet);
} else {
chunks.push({ title: trimmed, notes: [] });
index += 1;
}
}

return (
<details ref={ref}>
<summary tabIndex={-1} className={styles.summary}>
{t('updateNotification_updated_version', { version })} {inlineLink}
</summary>
<div id={id} class={styles.detailsContent}>
<ul class={styles.list}>
{notes.map((note, index) => {
/**
* Note: Doing this here as a very specific 'view' concern
* Note: using the `if` + `.slice` to avoid regex
* Note: `.slice` is safe on `•` because it is a single Unicode character
* and is represented by a single UTF-16 code unit.
*/
let trimmed = note.trim();
if (trimmed.startsWith('•')) {
trimmed = trimmed.slice(1).trim();
}
return <li key={note + index}>{trimmed}</li>;
})}
</ul>
{chunks.map((chunk, index) => {
return (
<Fragment key={chunk.title + index}>
{chunk.title && <p class={styles.title}>{chunk.title}</p>}
<ul class={styles.list}>
{chunk.notes.map((note, index) => {
return <li key={note + index}>{note}</li>;
})}
</ul>
</Fragment>
);
})}
</div>
</details>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,17 @@
}

.detailsContent {
padding-inline: var(--sp-2);
margin-top: var(--sp-2);
margin-top: var(--sp-4);
text-align: left;
max-width: 380px; /* just a value that looks below it's centered heading */
margin-left: auto;
margin-right: auto;
}
.title {
padding: 0.5rem 0;
}

.list {
margin-left: var(--sp-20);
margin-left: 1.5rem;
li {
list-style: disc
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,21 @@ test.describe('newtab update notifications', () => {
await page.getByRole('button', { name: 'Dismiss' }).click();
await ntp.mocks.waitForCallCount({ method: 'updateNotification_dismiss', count: 1 });
});
test('handles multiple lists', async ({ page }, workerInfo) => {
const ntp = NewtabPage.create(page, workerInfo);
await ntp.reducedMotion();
await ntp.openPage({ updateNotification: 'multipleSections' });
await page.getByRole('link', { name: "what's new" }).click();
await expect(page.locator('[data-entry-point="updateNotification"]')).toMatchAriaSnapshot(`
- group:
- list:
- listitem: We're excited to introduce a new browsing feature - Fire Windows. These special windows work the same way as normal windows, except they isolate your activity from other browsing data and self-destruct when closed. This means you can use a Fire Window to browse without saving local history or to sign into a site with a different account. You can open a new Fire Window anytime from the Fire Button menu.
- listitem: Try the new bookmark management view that opens in a tab for more robust bookmark organization.
- paragraph: For Privacy Pro subscribers
- list:
- listitem: VPN notifications are now available to help communicate VPN status.
- listitem: Some apps aren't compatible with VPNs. You can now exclude these apps to use them while connected to the VPN.
- listitem: Visit https://duckduckgo.com/pro for more information.
`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,18 @@ export const updateNotificationExamples = {
version: '1.91',
},
},
multipleSections: {
content: {
// prettier-ignore
notes: [
`• We're excited to introduce a new browsing feature - Fire Windows. These special windows work the same way as normal windows, except they isolate your activity from other browsing data and self-destruct when closed. This means you can use a Fire Window to browse without saving local history or to sign into a site with a different account. You can open a new Fire Window anytime from the Fire Button menu.`,
`• Try the new bookmark management view that opens in a tab for more robust bookmark organization.`,
`For Privacy Pro subscribers`,
`• VPN notifications are now available to help communicate VPN status.`,
`• Some apps aren't compatible with VPNs. You can now exclude these apps to use them while connected to the VPN.`,
`• Visit https://duckduckgo.com/pro for more information.`,
],
version: '0.98.4',
},
},
};
Loading