Bug 1944690 - Local model managment landing page skeleton and navigation r=rpl,fluent-reviewers,bolsson

Introduce lit components to about:addons with special rendering of mlmodel list intro. Conditionally show this and not empty list message.

Differential Revision: https://phabricator.services.mozilla.com/D239881
This commit is contained in:
Ed Lee
2025-03-05 18:30:23 +00:00
parent eacddc0c21
commit 1ce3881e0e
7 changed files with 96 additions and 6 deletions

View File

@@ -8,4 +8,9 @@
addon-category-mlmodel = On-device AI
addon-category-mlmodel-title =
.title = On-device AI
mlmodel-heading = Manage Local AI Models
mlmodel-description =
Placeholder text. On-device AI Models are optional components that get added to { -brand-short-name } when they are first needed by a feature or extension you use.
They process your queries on your device, meaning they are more private than online AI providers, but sometimes slower depending on the performance of your device. <a data-l10n-name="learn-more">Learn more</a>

View File

@@ -58,6 +58,10 @@
defer
src="chrome://mozapps/content/extensions/aboutaddons.js"
></script>
<script
src="chrome://mozapps/content/extensions/components/mlmodel-list-intro.mjs"
type="module"
></script>
<script
type="module"
src="chrome://global/content/elements/moz-message-bar.mjs"

View File

@@ -3695,18 +3695,26 @@ class AddonList extends HTMLElement {
}
frag.appendChild(this.pendingUninstallStack);
if (this.type == "mlmodel") {
frag.appendChild(document.createElement("mlmodel-list-intro"));
}
// Render the sections.
for (let i = 0; i < sectionedAddons.length; i++) {
this.sections[i].node = this.renderSection(sectionedAddons[i], i);
frag.appendChild(this.sections[i].node);
}
// Render the placeholder that is shown when all sections are empty.
// This call is after rendering the sections, because its visibility
// is controlled through the general sibling combinator relative to
// the sections (section ~).
let message = this.createEmptyListMessage();
frag.appendChild(message);
// Add the "empty list message" elements (but omit it in the list view
// related to the "mlmodel" type).
if (this.type != "mlmodel") {
// Render the placeholder that is shown when all sections are empty.
// This call is after rendering the sections, because its visibility
// is controlled through the general sibling combinator relative to
// the sections (section ~).
let message = this.createEmptyListMessage();
frag.appendChild(message);
}
// Make sure fluent has set all the strings before we render. This will
// avoid the height changing as strings go from 0 height to having text.

View File

@@ -0,0 +1,8 @@
/* 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/. */
p {
margin-bottom: var(--space-xxlarge);
white-space: pre-wrap;
}

View File

@@ -0,0 +1,31 @@
/* 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 https://mozilla.org/MPL/2.0/. */
import { html } from "chrome://global/content/vendor/lit.all.mjs";
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
export class MLModelListIntro extends MozLitElement {
render() {
return this.template;
}
get template() {
return html`
<link
href="chrome://mozapps/content/extensions/components/mlmodel-list-intro.css"
rel="stylesheet"
/>
<header>
<p data-l10n-id="mlmodel-description">
<a
data-l10n-name="learn-more"
is="moz-support-link"
support-page="local-models"
></a>
</p>
</header>
`;
}
}
customElements.define("mlmodel-list-intro", MLModelListIntro);

View File

@@ -11,6 +11,8 @@ toolkit.jar:
content/mozapps/extensions/aboutaddonsCommon.js (content/aboutaddonsCommon.js)
content/mozapps/extensions/aboutaddons.css (content/aboutaddons.css)
content/mozapps/extensions/abuse-reports.js (content/abuse-reports.js)
content/mozapps/extensions/components (content/components/*.css)
content/mozapps/extensions/components (content/components/*.mjs)
content/mozapps/extensions/drag-drop-addon-installer.js (content/drag-drop-addon-installer.js)
content/mozapps/extensions/shortcuts.css (content/shortcuts.css)
content/mozapps/extensions/shortcuts.js (content/shortcuts.js)

View File

@@ -56,6 +56,11 @@ add_task(async function testModelHubProvider() {
!enabledSection.querySelector(".list-section-heading"),
"No heading for mlmodel"
);
is(
enabledSection.previousSibling.localName,
"mlmodel-list-intro",
"Model hub custom section is shown"
);
let promiseListUpdated = BrowserTestUtils.waitForEvent(
enabledSection.closest("addon-list"),
@@ -77,5 +82,32 @@ add_task(async function testModelHubProvider() {
"Got the expected number of mlmodel entries"
);
promiseListUpdated = BrowserTestUtils.waitForEvent(
enabledSection.closest("addon-list"),
"remove"
);
info("Uninstall the last one of the mlmodel entries");
const mlmodelmock1 = await AddonManager.getAddonByID(
"mockmodel1@tests.mozilla.org"
);
await mlmodelmock1.uninstall();
info("Wait for the list of mlmodel entries to be updated");
await promiseListUpdated;
enabledSection = getSection(doc, "mlmodel-enabled-section");
is(
enabledSection.children.length,
0,
"Expect mlmodel add-ons list view to be empty"
);
let emptyMessageFindModeOnAMO = doc.querySelector("#empty-addons-message");
is(
emptyMessageFindModeOnAMO,
null,
"Expect no #empty-addons-message element in the empty mlmodel list view"
);
await closeView(win);
});