tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit f142c9138f1d943190c5a8f5b4385ae86a6d0985
parent d8715cf302fb2933b6264b68de900dca740479b6
Author: Chloe Zhou <chloezhouny@gmail.com>
Date:   Sat, 20 Dec 2025 01:55:36 +0000

Bug 2005380 - Create firstrun model picker screen r=pdahiya,fluent-reviewers,omc-reviewers,ai-frontend-reviewers,bolsson

**Summay**
This patch implements the model picker screen for the AI Window first-run flow. Users select their preferred AI model from three options, and the selection is stored in browser.aiwindow.firstrun.modelChoice preference (values: "1", "2", or "3"). The flow uses the AboutWelcome bundle.

**Test Steps**
1. In about:config, set browser.tabs.allow_transparent_browser and browser.aiwindow.enabled to true
2. Navigate to chrome://browser/content/aiwindow/firstrun.html
3. Verify intro screen appears with gradient title animation
4. Wait ~20 seconds for auto-advance to model picker screen //(Note: Auto-advance timing will be configured in a follow-up patch)//
5. Select a model card and click "Let's go" button
6. Verify screen is navigated to chrome://browser/content/aiwindow/aiwindow.html page
7. Verify browser.aiwindow.firstrun.modelChoice pref is set to selected value ("1", "2", or "3")

Differential Revision: https://phabricator.services.mozilla.com/D276705

Diffstat:
Mbrowser/app/profile/firefox.js | 1+
Abrowser/components/aiwindow/ui/assets/model-choice-1.svg | 5+++++
Abrowser/components/aiwindow/ui/assets/model-choice-2.svg | 5+++++
Abrowser/components/aiwindow/ui/assets/model-choice-3.svg | 5+++++
Mbrowser/components/aiwindow/ui/content/firstrun.css | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mbrowser/components/aiwindow/ui/content/firstrun.js | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mbrowser/components/aiwindow/ui/jar.mn | 3+++
Mbrowser/components/aiwindow/ui/test/browser/browser_aiwindow_firstrun.js | 18++++++++++++------
Mbrowser/locales-preview/aiWindow.ftl | 9+++++++++
Mtoolkit/components/messaging-system/lib/SpecialMessageActions.sys.mjs | 1+
10 files changed, 319 insertions(+), 28 deletions(-)

diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js @@ -2255,6 +2255,7 @@ pref("browser.aiwindow.enabled", false); pref("browser.aiwindow.endpoint", "https://mlpa-prod-prod-mozilla.global.ssl.fastly.net/v1"); pref("browser.aiwindow.insights", false); pref("browser.aiwindow.insightsLogLevel", "Warn"); +pref("browser.aiwindow.firstrun.modelChoice", ""); pref("browser.aiwindow.model", ""); // Block insecure active content on https pages diff --git a/browser/components/aiwindow/ui/assets/model-choice-1.svg b/browser/components/aiwindow/ui/assets/model-choice-1.svg @@ -0,0 +1,4 @@ +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="none" viewBox="0 0 100 100"><path fill="url(#a)" d="m73 40-15-1-1-1 15-21 1-2-19 5-14 24 1 1h14q3 1 2 2L31 86q1 1 2-1l41-41q2-3-1-4" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#b)" d="m54 20 19-5-1-1H57z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#c)" d="m54 20 19-5-1-1H57z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#d)" d="M57 14H44l10 6z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#e)" d="M57 14H44l10 6z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#f)" d="M57 14H44l10 6z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#g)" d="m55 46-14-1-1-1 14-24-10-6-1 1-17 34 2 4h16v1L30 85l1 1 26-39z" transform="matrix(.8 0 0 .8 10 10)"/><defs><linearGradient id="a" x1="20" x2="75" y1="21" y2="72" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="b" x1="42" x2="97" y1="-3" y2="48" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="c" x1="46" x2="103" y1="2" y2="52" gradientUnits="userSpaceOnUse"><stop stop-color="#f942ff"/><stop offset="0" stop-color="#cf3aff"/><stop offset="1" stop-color="#6625ff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="d" x1="37" x2="92" y1="2" y2="53" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="e" x1="48" x2="89" y1="11" y2="68" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="f" x1="42" x2="99" y1="6" y2="57" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cf3aff"/><stop offset="1" stop-color="#6625ff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="g" x1="24" x2="65" y1="28" y2="85" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient></defs></svg> +\ No newline at end of file diff --git a/browser/components/aiwindow/ui/assets/model-choice-2.svg b/browser/components/aiwindow/ui/assets/model-choice-2.svg @@ -0,0 +1,4 @@ +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="none" viewBox="0 0 100 100"><path fill="url(#a)" d="M52 43s23-1 38 22l-7-2s10 5 14 25c-2-4-11-16-22-17q2 0 5 8h-1a79 79 0 0 0-30-16c-10-2 3-20 3-20" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#b)" d="m5 36 17 14-5 22 18-11 19 11-5-22 17-14-22-2-9-20-8 21z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#c)" d="M22 50 5 36l22-2 8-20-1-2-1 1-9 18-19 3a2 2 0 0 0-2 4l14 14-3 19 1 2 1-1z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#d)" d="M22 50 5 36l22-2 8-20-1-2-1 1-9 18-19 3a2 2 0 0 0-2 4l14 14-3 19 1 2 1-1z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#e)" d="m66 34-19-4-10-17-1-1-1 2 9 20 22 2-17 15 5 21-19-11-19 11v2h2l17-9 18 9q4 1 3-3l-3-19 14-14q3-3-1-4" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#f)" d="m66 34-19-4-10-17-1-1-1 2 9 20 22 2-17 15 5 21-19-11-19 11v2h2l17-9 18 9q4 1 3-3l-3-19 14-14q3-3-1-4" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#g)" d="M36 12h-2l1 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#h)" d="M36 12h-2l1 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#i)" d="M36 12h-2l1 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#j)" d="m15 73 1 1 1-2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#k)" d="m15 73 1 1 1-2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#l)" d="m15 73 1 1 1-2z" transform="matrix(.8 0 0 .8 10 10)"/><defs><linearGradient id="a" x1="94" x2="36" y1="71" y2="50" gradientUnits="userSpaceOnUse"><stop stop-color="#ffeb49"/><stop offset="1" stop-color="#f60"/><stop offset="1" stop-color="#d22232"/><stop offset="1" stop-color="#be0449"/></linearGradient><linearGradient id="b" x1="10" x2="90" y1="22" y2="103" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="c" x1="10" x2="90" y1="22" y2="103" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="e" x1="28" x2="108" y1="5" y2="85" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="f" x1="23" x2="47" y1="26" y2="63" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#d33aff"/><stop offset="0" stop-color="#9f30ff"/><stop offset="0" stop-color="#7528ff"/><stop offset="1" stop-color="#5421ff"/><stop offset="1" stop-color="#3c1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="g" x1="28" x2="108" y1="5" y2="85" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="i" x1="38" x2="62" y1="16" y2="53" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#d33aff"/><stop offset="0" stop-color="#9f30ff"/><stop offset="0" stop-color="#7528ff"/><stop offset="1" stop-color="#5421ff"/><stop offset="1" stop-color="#3c1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="j" x1="-12" x2="68" y1="44" y2="125" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="l" x1="-4" x2="21" y1="44" y2="80" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#d33aff"/><stop offset="0" stop-color="#9f30ff"/><stop offset="0" stop-color="#7528ff"/><stop offset="1" stop-color="#5421ff"/><stop offset="1" stop-color="#3c1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><radialGradient id="d" cx="0" cy="0" r="1" gradientTransform="matrix(63.9273 0 0 63.9272 11 49)" gradientUnits="userSpaceOnUse"><stop stop-color="#e552fd"/><stop offset="0" stop-color="#e850fd"/><stop offset="0" stop-color="#f248fe"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f641ff"/><stop offset="0" stop-color="#ec40ff"/><stop offset="1" stop-color="#dc3cff"/><stop offset="1" stop-color="#c538ff"/><stop offset="1" stop-color="#a832ff"/><stop offset="1" stop-color="#832bff"/><stop offset="1" stop-color="#5922ff"/><stop offset="1" stop-color="#2919ff"/></radialGradient><radialGradient id="h" cx="0" cy="0" r="1" gradientTransform="matrix(63.9273 0 0 63.9272 11 49)" gradientUnits="userSpaceOnUse"><stop stop-color="#e552fd"/><stop offset="0" stop-color="#e850fd"/><stop offset="0" stop-color="#f248fe"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f641ff"/><stop offset="0" stop-color="#ec40ff"/><stop offset="1" stop-color="#dc3cff"/><stop offset="1" stop-color="#c538ff"/><stop offset="1" stop-color="#a832ff"/><stop offset="1" stop-color="#832bff"/><stop offset="1" stop-color="#5922ff"/><stop offset="1" stop-color="#2919ff"/></radialGradient><radialGradient id="k" cx="0" cy="0" r="1" gradientTransform="matrix(63.9272 0 0 63.9273 11 49)" gradientUnits="userSpaceOnUse"><stop stop-color="#e552fd"/><stop offset="0" stop-color="#e850fd"/><stop offset="0" stop-color="#f248fe"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f641ff"/><stop offset="0" stop-color="#ec40ff"/><stop offset="1" stop-color="#dc3cff"/><stop offset="1" stop-color="#c538ff"/><stop offset="1" stop-color="#a832ff"/><stop offset="1" stop-color="#832bff"/><stop offset="1" stop-color="#5922ff"/><stop offset="1" stop-color="#2919ff"/></radialGradient></defs></svg> +\ No newline at end of file diff --git a/browser/components/aiwindow/ui/assets/model-choice-3.svg b/browser/components/aiwindow/ui/assets/model-choice-3.svg @@ -0,0 +1,4 @@ +<!-- 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="none" viewBox="0 0 100 100"><path fill="url(#a)" d="m19 44-3 3-1 2c0 9 27 8 29 8q4 0 2 2c-4 6-28 6-23 18 3 5 16 5 17 7 1 5-15 0-19 15h1q6-4 13-3c7 0 17 0 21-6l1-3c0-9-23-8-15-16 7-4 21-6 22-13 0-15-52 1-45-13" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#b)" d="M22 41v4l13 1h4l-1-2 3-5q-3 1-5-2c-3-4 1-7 1-7L81 6 36 30s-4 1-6-1l-2-4-1 2-8 12z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#c)" d="m22 41-3-2-2 3q-1 2 1 3h4z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#d)" d="m22 41-3-2-2 3q-1 2 1 3h4z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#e)" d="m41 39-2 5v2l4-1 37-20 4-5 1-3v-2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#f)" d="m41 39-2 5v2l4-1 37-20 4-5 1-3v-2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#g)" d="M30 29q5 2 6 1L81 6h-1l-6-4h-4L31 23l-3 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#h)" d="M30 29q5 2 6 1L81 6h-1l-6-4h-4L31 23l-3 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#i)" d="M36 37q2 3 5 2l1-2 43-23v-2l-4-6-44 24s-4 3-1 7" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#j)" d="M36 37q2 3 5 2l1-2 43-23v-2l-4-6-44 24s-4 3-1 7" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#k)" d="M36 37q2 3 5 2l1-2 43-23v-2l-4-6-44 24s-4 3-1 7" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#l)" d="m19 44-3 3-1 2c0 9 27 8 29 8q4 0 2 2c-4 6-28 6-23 18 3 5 16 5 17 7 1 5-15 0-19 15h1q6-4 13-3c7 0 17 0 21-6l1-3c0-9-23-8-15-16 7-4 21-6 22-13 0-15-52 1-45-13" transform="matrix(.8 0 0 .8 10 10)"/><defs><linearGradient id="a" x1="39" x2="39" y1="44" y2="98" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f441ff"/><stop offset="0" stop-color="#ac33ff"/><stop offset="1" stop-color="#7428ff"/><stop offset="1" stop-color="#4b20ff"/><stop offset="1" stop-color="#321bff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="b" x1="56" x2="68" y1="20" y2="53" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="c" x1="56" x2="68" y1="20" y2="53" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="d" x1="18" x2="23" y1="39" y2="45" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="e" x1="56" x2="68" y1="20" y2="53" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="f" x1="57" x2="69" y1="22" y2="45" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="0" stop-color="#7127ff"/><stop offset="0" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="g" x1="56" x2="68" y1="20" y2="53" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="h" x1="53" x2="63" y1="10" y2="62" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="i" x1="58" x2="70" y1="19" y2="52" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="j" x1="60" x2="72" y1="18" y2="51" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="k" x1="60" x2="72" y1="20" y2="44" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="0" stop-color="#7127ff"/><stop offset="0" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="l" x1="30" x2="96" y1="-49" y2="114" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f441ff"/><stop offset="0" stop-color="#ac33ff"/><stop offset="1" stop-color="#7428ff"/><stop offset="1" stop-color="#4b20ff"/><stop offset="1" stop-color="#321bff"/><stop offset="1" stop-color="#2919ff"/></linearGradient></defs></svg> +\ No newline at end of file diff --git a/browser/components/aiwindow/ui/content/firstrun.css b/browser/components/aiwindow/ui/content/firstrun.css @@ -1,7 +1,9 @@ /* 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/. */ - +:root { + --background-color-canvas: transparent; +} @keyframes springUp { from { opacity: 0; @@ -14,29 +16,140 @@ } #multi-stage-message-root { - #mainContentHeader { - opacity: 0; - animation: springUp 0.5s ease-out forwards; - animation-delay: 0.3s; - background: linear-gradient(91deg, #7630c0 22.04%, #5c66ee 78.7%); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - } + --bg-white: light-dark(#fff, #fff); + --bg-transparent: transparent; + --tile-border-color: #f1e7f8; + --shadow-color: rgb(59 34 121); + + --gradient-button: linear-gradient(97deg, #8341ca -31.39%, #656fff 90.52%); + --gradient-selected-border: linear-gradient(117deg, #321bfd -17.87%, #cf30e2 52.93%, #f90 89.02%, #f5c451 109.44%); .main-content, .section-main, - .screen, .dialog-initial, .onboardingContainer { box-shadow: none; } .onboardingContainer .screen[pos="center"] { - background-color: transparent; + background-color: var(--bg-transparent); + } + + #mainContentHeader { + /* stylelint-disable-next-line -- using linear gradient for text effect */ + background: linear-gradient(91deg, #7630c0 22.04%, #5c66ee 78.7%); + background-clip: text; + /* stylelint-disable-next-line -- transparent needed for gradient text effect */ + color: var(--bg-transparent); } - button.primary { - display: none; + .screen.AI_WINDOW_INTRO { + #mainContentHeader { + opacity: 0; + animation: springUp 0.3s ease-in forwards; + animation-delay: 0.3s; + } + } + + .screen.AI_WINDOW_CHOOSE_MODEL { + h2, + p { + letter-spacing: 0.3px; + line-height: normal; + } + + .welcome-text h2 { + opacity: 0.8; + margin-top: var(--space-medium); + } + + button.primary { + width: calc(var(--size-item-large) * 7); + height: var(--size-item-xlarge); + display: flex; + justify-content: center; + align-items: center; + gap: var(--space-small); + padding: var(--space-xsmall) var(--space-large); + margin: 0 auto; + border: var(--border-width) solid var(--border-color-transparent); + border-radius: var(--border-radius-medium); + background: var(--gradient-button); + color: var(--button-text-color-primary); + text-align: center; + font-size: var(--button-font-size); + font-weight: var(--button-font-weight); + letter-spacing: -0.3px; + cursor: pointer; + } + + &:not(:has(.icon.selected)) button.primary { + opacity: 0.5; + pointer-events: none; + cursor: default; + } + } + + .tiles-single-select-section.single-select { + gap: var(--space-large); + margin-top: calc(var(--space-xsmall) * 8); + margin-bottom: var(--space-xxlarge); + + .select-item { + width: calc(var(--size-item-large) * 7); + height: calc(var(--size-item-medium) * 11); + padding-block: calc(var(--space-xsmall) * 9) 0; + /* stylelint-disable-next-line -- custom border color per Figma design */ + border: var(--border-width) solid var(--tile-border-color); + display: flex; + flex-direction: column; + justify-content: start; + align-items: center; + gap: 0; + padding-inline: var(--space-medium); + box-sizing: border-box; + border-radius: var(--border-radius-large); + /* stylelint-disable-next-line -- using white for consistent background */ + background: color-mix(in srgb, var(--bg-white) 60%, var(--bg-transparent)); + + .label-text { + margin-top: calc(var(--space-xsmall) * 5); + margin-bottom: 0; + letter-spacing: 0.5px; + opacity: 0.8; + line-height: normal; + } + + .body-text { + opacity: 0.8; + line-height: normal; + } + + .icon { + width: calc(var(--size-item-xlarge) * 2); + height: calc(var(--size-item-xlarge) * 2); + display: flex; + justify-content: center; + align-items: center; + flex-shrink: 0; + } + + &:hover:not(:has(.selected)) { + /* stylelint-disable-next-line -- using white for hover state */ + background: var(--bg-white); + cursor: pointer; + } + + &:has(.selected) { + border: calc(var(--border-width) * 2) solid var(--border-color-transparent); + background: + linear-gradient(#fff, #fff) padding-box, + var(--gradient-selected-border) border-box; + /* stylelint-disable-next-line -- custom shadow color per Figma design */ + box-shadow: + 0 3px 16px 0 color-mix(in srgb, var(--shadow-color) 12%, var(--bg-transparent)), + 0 1px 2px 0 color-mix(in srgb, var(--shadow-color) 20%, var(--bg-transparent)); + } + } } } diff --git a/browser/components/aiwindow/ui/content/firstrun.js b/browser/components/aiwindow/ui/content/firstrun.js @@ -2,19 +2,28 @@ * 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/. */ -const SMART_ASSIST_URL = "chrome://browser/content/genai/smartAssist.html"; +const lazy = {}; +const { topChromeWindow } = window.browsingContext; + +ChromeUtils.defineESModuleGetters(lazy, { + AboutWelcomeParent: "resource:///actors/AboutWelcomeParent.sys.mjs", + AIWindow: + "moz-src:///browser/components/aiwindow/ui/modules/AIWindow.sys.mjs", +}); +const MODEL_PREF = "browser.aiwindow.firstrun.modelChoice"; +const BRAND_DARK_PURPLE = "#210340"; const AI_WINDOW_CONFIG = { id: "AI_WINDOW_WELCOME", template: "spotlight", transitions: true, modal: "tab", - backdrop: - "radial-gradient(circle at 50% 90%, rgba(253, 244, 243, 1) 0%, rgba(253, 244, 243, 1) 30%, rgba(216, 202, 247, 1) 100%)", + backdrop: "transparent", screens: [ { - id: "AW_AI_WINDOW_WELCOME", + id: "AI_WINDOW_INTRO", auto_advance: "primary_button", + force_hide_steps_indicator: true, content: { fullscreen: true, hide_secondary_section: "responsive", @@ -25,13 +34,12 @@ const AI_WINDOW_CONFIG = { overflow: "hidden", }, title: { - fontWeight: 400, + fontWeight: 350, fontSize: "39px", + letterSpacing: 0, lineHeight: "56px", textAlign: "center", string_id: "aiwindow-firstrun-title", - color: "transparent", - letterSpacing: "0px", }, primary_button: { label: "", @@ -41,16 +49,151 @@ const AI_WINDOW_CONFIG = { }, }, }, + { + id: "AI_WINDOW_CHOOSE_MODEL", + force_hide_steps_indicator: true, + content: { + position: "center", + background: "transparent", + screen_style: { + width: "750px", + }, + title: { + string_id: "aiwindow-firstrun-model-title", + fontSize: "40px", + fontWeight: "350", + letterSpacing: 0, + lineHeight: "normal", + }, + subtitle: { + string_id: "aiwindow-firstrun-model-subtitle", + fontSize: "17px", + fontWeight: 320, + color: BRAND_DARK_PURPLE, + }, + tiles: { + type: "single-select", + selected: "none", + autoTrigger: false, + action: { + picker: "<event>", + }, + data: [ + { + id: "model_1", + label: { + string_id: "aiwindow-firstrun-model-fast-label", + fontSize: "20px", + fontWeight: 613, + color: BRAND_DARK_PURPLE, + }, + icon: { + background: + 'center / contain no-repeat url("chrome://browser/content/aiwindow/assets/model-choice-1.svg")', + }, + body: { + string_id: "aiwindow-firstrun-model-fast-body", + color: BRAND_DARK_PURPLE, + fontSize: "15px", + fontWeight: 320, + }, + action: { + type: "SET_PREF", + data: { + pref: { + name: MODEL_PREF, + value: "1", + }, + }, + }, + }, + { + id: "model_2", + label: { + string_id: "aiwindow-firstrun-model-allpurpose-label", + fontSize: "20px", + fontWeight: 613, + color: BRAND_DARK_PURPLE, + }, + icon: { + background: + 'center / contain no-repeat url("chrome://browser/content/aiwindow/assets/model-choice-2.svg")', + }, + body: { + string_id: "aiwindow-firstrun-model-allpurpose-body", + color: BRAND_DARK_PURPLE, + fontSize: "15px", + fontWeight: 320, + }, + action: { + type: "SET_PREF", + data: { + pref: { + name: MODEL_PREF, + value: "2", + }, + }, + }, + }, + { + id: "model_3", + label: { + string_id: "aiwindow-firstrun-model-personal-label", + fontSize: "20px", + fontWeight: 613, + color: BRAND_DARK_PURPLE, + }, + icon: { + background: + 'center / contain no-repeat url("chrome://browser/content/aiwindow/assets/model-choice-3.svg")', + }, + body: { + string_id: "aiwindow-firstrun-model-personal-body", + color: BRAND_DARK_PURPLE, + fontSize: "15px", + fontWeight: 320, + }, + action: { + type: "SET_PREF", + data: { + pref: { + name: MODEL_PREF, + value: "3", + }, + }, + }, + }, + ], + }, + primary_button: { + label: { + string_id: "aiwindow-firstrun-button", + }, + action: { + navigate: true, + }, + }, + }, + }, ], }; function renderFirstRun() { + const AWParent = new lazy.AboutWelcomeParent(); + const receive = name => data => + AWParent.onContentMessage( + `AWPage:${name}`, + data, + topChromeWindow.gBrowser.selectedBrowser + ); + window.AWGetFeatureConfig = () => AI_WINDOW_CONFIG; window.AWEvaluateScreenTargeting = screens => screens; window.AWGetSelectedTheme = () => ({}); window.AWGetInstalledAddons = () => []; + window.AWSendToParent = (name, data) => receive(name)(data); window.AWFinish = () => { - window.location.href = SMART_ASSIST_URL; + window.location.href = lazy.AIWindow.newTabURL; }; const script = document.createElement("script"); diff --git a/browser/components/aiwindow/ui/jar.mn b/browser/components/aiwindow/ui/jar.mn @@ -14,6 +14,9 @@ browser.jar: content/browser/aiwindow/components/ai-window.css (components/ai-window/ai-window.css) content/browser/aiwindow/components/input-cta.css (components/input-cta/input-cta.css) content/browser/aiwindow/components/input-cta.mjs (components/input-cta/input-cta.mjs) + content/browser/aiwindow/assets/model-choice-1.svg (assets/model-choice-1.svg) + content/browser/aiwindow/assets/model-choice-2.svg (assets/model-choice-2.svg) + content/browser/aiwindow/assets/model-choice-3.svg (assets/model-choice-3.svg) content/browser/aiwindow/firstrun.html (content/firstrun.html) content/browser/aiwindow/firstrun.css (content/firstrun.css) content/browser/aiwindow/firstrun.js (content/firstrun.js) diff --git a/browser/components/aiwindow/ui/test/browser/browser_aiwindow_firstrun.js b/browser/components/aiwindow/ui/test/browser/browser_aiwindow_firstrun.js @@ -18,16 +18,22 @@ add_task(async function test_firstrun_welcome_screen_renders() { await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { await ContentTaskUtils.waitForCondition( - () => content.document.querySelector(".screen.AW_AI_WINDOW_WELCOME"), - "Wait for the AI Window welcome screen to be rendered" + () => content.document.querySelector(".screen.AI_WINDOW_INTRO"), + "Wait for the AI Window intro screen to be rendered" ); - const welcomeScreen = content.document.querySelector( - ".screen.AW_AI_WINDOW_WELCOME" + const introScreen = content.document.querySelector( + ".screen.AI_WINDOW_INTRO" ); Assert.ok( - welcomeScreen, - "The welcome screen with class 'screen AW_AI_WINDOW_WELCOME' should be present" + introScreen, + "The intro screen with class 'screen AI_WINDOW_INTRO' should be present" + ); + + await ContentTaskUtils.waitForCondition( + () => content.document.querySelector(".screen.AI_WINDOW_CHOOSE_MODEL"), + "Wait for the AI Window choose model screen to be rendered", + 25000 ); }); diff --git a/browser/locales-preview/aiWindow.ftl b/browser/locales-preview/aiWindow.ftl @@ -25,3 +25,12 @@ aiwindow-input-cta-label-navigate = Navigate ## Firstrun onboarding aiwindow-firstrun-title = Welcome to Smart Window +aiwindow-firstrun-model-title = Pick a model to start +aiwindow-firstrun-model-subtitle = Switch anytime to find your best fit. +aiwindow-firstrun-model-fast-label = Fastest +aiwindow-firstrun-model-fast-body = Best for quick answers to everyday questions +aiwindow-firstrun-model-allpurpose-label = All-purpose +aiwindow-firstrun-model-allpurpose-body = Best for a variety of quick and complex features +aiwindow-firstrun-model-personal-label = Personalization +aiwindow-firstrun-model-personal-body = Best for learning with you +aiwindow-firstrun-button = Let’s go diff --git a/toolkit/components/messaging-system/lib/SpecialMessageActions.sys.mjs b/toolkit/components/messaging-system/lib/SpecialMessageActions.sys.mjs @@ -248,6 +248,7 @@ export const SpecialMessageActions = { // Array of prefs that are allowed to be edited by SET_PREF const allowedPrefs = [ "browser.aboutwelcome.didSeeFinalScreen", + "browser.aiwindow.firstrun.modelChoice", "browser.crashReports.unsubmittedCheck.autoSubmit2", "browser.dataFeatureRecommendations.enabled", "browser.ipProtection.enabled",