Revert "Bug 1956042 - Support multiple instances of SingleSelect on the same aboutwelcome screen r=omc-reviewers,jprickett,mviar" for causing failures at browser_aboutwelcome_multiselect.js.
This reverts commit 9165ff110c.
This commit is contained in:
committed by
abutkovits@mozilla.com
parent
2292b5933e
commit
fdfa96ea29
@@ -155,13 +155,8 @@ export const ContentTiles = props => {
|
||||
content={{ tiles: tile }}
|
||||
activeTheme={props.activeTheme}
|
||||
handleAction={props.handleAction}
|
||||
activeSingleSelectSelections={
|
||||
props.activeSingleSelectSelections
|
||||
}
|
||||
setActiveSingleSelectSelection={
|
||||
props.setActiveSingleSelectSelection
|
||||
}
|
||||
singleSelectId={`single-select-${index}`}
|
||||
activeSingleSelect={props.activeSingleSelect}
|
||||
setActiveSingleSelect={props.setActiveSingleSelect}
|
||||
/>
|
||||
)}
|
||||
{tile.type === "mobile_downloads" && tile.data && (
|
||||
|
||||
@@ -199,12 +199,11 @@ export const MultiStageAboutWelcome = props => {
|
||||
// multi select screen.
|
||||
const [activeMultiSelects, setActiveMultiSelects] = useState({});
|
||||
|
||||
// Save the active single select state for each screen as an object keyed
|
||||
// Save the active single select state for each screen as string value keyed
|
||||
// by screen id. Similar to above, this allows us to remember the state of
|
||||
// each screen's single select picker when navigating back and forth between
|
||||
// screens, and allows us to have multiple single selects on a screen.
|
||||
const [activeSingleSelectSelections, setActiveSingleSelectSelections] =
|
||||
useState({});
|
||||
// screens.
|
||||
const [activeSingleSelects, setActiveSingleSelects] = useState({});
|
||||
|
||||
// Get the active theme so the rendering code can make it selected
|
||||
// by default.
|
||||
@@ -284,25 +283,14 @@ export const MultiStageAboutWelcome = props => {
|
||||
});
|
||||
};
|
||||
|
||||
const setActiveSingleSelectSelection = (
|
||||
valueOrFn,
|
||||
singleSelectId
|
||||
) => {
|
||||
setActiveSingleSelectSelections(prevState => {
|
||||
const currentScreenSelections = prevState[currentScreen.id] || {};
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
[currentScreen.id]: {
|
||||
...currentScreenSelections,
|
||||
[singleSelectId]:
|
||||
typeof valueOrFn === "function"
|
||||
? valueOrFn(prevState[currentScreen.id])
|
||||
: valueOrFn,
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
const setActiveSingleSelect = valueOrFn =>
|
||||
setActiveSingleSelects(prevState => ({
|
||||
...prevState,
|
||||
[currentScreen.id]:
|
||||
typeof valueOrFn === "function"
|
||||
? valueOrFn(prevState[currentScreen.id])
|
||||
: valueOrFn,
|
||||
}));
|
||||
|
||||
return index === order ? (
|
||||
<WelcomeScreen
|
||||
@@ -328,10 +316,8 @@ export const MultiStageAboutWelcome = props => {
|
||||
activeMultiSelect={activeMultiSelects[currentScreen.id]}
|
||||
setActiveMultiSelect={setActiveMultiSelect}
|
||||
autoAdvance={currentScreen.auto_advance}
|
||||
activeSingleSelectSelections={
|
||||
activeSingleSelectSelections[currentScreen.id]
|
||||
}
|
||||
setActiveSingleSelectSelection={setActiveSingleSelectSelection}
|
||||
activeSingleSelect={activeSingleSelects[currentScreen.id]}
|
||||
setActiveSingleSelect={setActiveSingleSelect}
|
||||
negotiatedLanguage={negotiatedLanguage}
|
||||
langPackInstallPhase={langPackInstallPhase}
|
||||
forceHideStepsIndicator={currentScreen.force_hide_steps_indicator}
|
||||
@@ -496,63 +482,8 @@ export class WelcomeScreen extends React.PureComponent {
|
||||
return AboutWelcomeUtils.handleUserAction({ type, data });
|
||||
}
|
||||
|
||||
logTelemetry({ value, event, source, props }) {
|
||||
AboutWelcomeUtils.sendActionTelemetry(props.messageId, source, event.name);
|
||||
|
||||
// Send additional telemetry if a messaging surface like feature callout is
|
||||
// dismissed via the dismiss button. Other causes of dismissal will be
|
||||
// handled separately by the messaging surface's own code.
|
||||
if (value === "dismiss_button" && !event.name) {
|
||||
AboutWelcomeUtils.sendDismissTelemetry(props.messageId, source);
|
||||
}
|
||||
}
|
||||
|
||||
async handleMigrationIfNeeded(action, props) {
|
||||
const hasMigrate = a =>
|
||||
a.type === "SHOW_MIGRATION_WIZARD" ||
|
||||
(a.type === "MULTI_ACTION" && a.data?.actions?.some(hasMigrate));
|
||||
|
||||
if (hasMigrate(action)) {
|
||||
await window.AWWaitForMigrationClose();
|
||||
AboutWelcomeUtils.sendActionTelemetry(props.messageId, "migrate_close");
|
||||
}
|
||||
}
|
||||
|
||||
applyThemeIfNeeded(action, event) {
|
||||
if (!action.theme) {
|
||||
return;
|
||||
}
|
||||
|
||||
const themeToUse =
|
||||
action.theme === "<event>"
|
||||
? event.currentTarget.value
|
||||
: this.props.initialTheme || action.theme;
|
||||
|
||||
this.props.setActiveTheme(themeToUse);
|
||||
window.AWSelectTheme(themeToUse);
|
||||
}
|
||||
|
||||
handlePickerAction(value) {
|
||||
const tileGroups = Array.isArray(this.props.content.tiles)
|
||||
? this.props.content.tiles
|
||||
: [this.props.content.tiles];
|
||||
|
||||
for (const tile of tileGroups) {
|
||||
if (!tile?.data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const opt of tile.data) {
|
||||
if (opt.id === value) {
|
||||
AboutWelcomeUtils.handleUserAction(opt.action);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleAction(event) {
|
||||
const { props } = this;
|
||||
let { props } = this;
|
||||
const value =
|
||||
event.currentTarget.value ?? event.currentTarget.getAttribute("value");
|
||||
const source = event.source || value;
|
||||
@@ -565,27 +496,20 @@ export class WelcomeScreen extends React.PureComponent {
|
||||
targetContent = { action: event.action };
|
||||
}
|
||||
|
||||
if (!targetContent) {
|
||||
if (!(targetContent && targetContent.action)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let action;
|
||||
if (Array.isArray(targetContent)) {
|
||||
for (const tile of targetContent) {
|
||||
const matchedTile = tile.data.find(t => t.id === value);
|
||||
if (matchedTile?.action) {
|
||||
action = matchedTile.action;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!targetContent.action) {
|
||||
return;
|
||||
} else {
|
||||
action = targetContent.action;
|
||||
}
|
||||
// Send telemetry before waiting on actions
|
||||
this.logTelemetry({ value, event, source, props });
|
||||
AboutWelcomeUtils.sendActionTelemetry(props.messageId, source, event.name);
|
||||
|
||||
// Send additional telemetry if a messaging surface like feature callout is
|
||||
// dismissed via the dismiss button. Other causes of dismissal will be
|
||||
// handled separately by the messaging surface's own code.
|
||||
if (value === "dismiss_button" && !event.name) {
|
||||
AboutWelcomeUtils.sendDismissTelemetry(props.messageId, source);
|
||||
}
|
||||
|
||||
let { action } = targetContent;
|
||||
action = JSON.parse(JSON.stringify(action));
|
||||
|
||||
if (action.collectSelect) {
|
||||
@@ -619,14 +543,32 @@ export class WelcomeScreen extends React.PureComponent {
|
||||
AboutWelcomeUtils.handleUserAction(action);
|
||||
}
|
||||
// Wait until migration closes to complete the action
|
||||
await this.handleMigrationIfNeeded(action, props);
|
||||
const hasMigrate = a =>
|
||||
a.type === "SHOW_MIGRATION_WIZARD" ||
|
||||
(a.type === "MULTI_ACTION" && a.data?.actions?.some(hasMigrate));
|
||||
if (hasMigrate(action)) {
|
||||
await window.AWWaitForMigrationClose();
|
||||
AboutWelcomeUtils.sendActionTelemetry(props.messageId, "migrate_close");
|
||||
}
|
||||
}
|
||||
|
||||
// A special tiles.action.theme value indicates we should use the event's value vs provided value.
|
||||
this.applyThemeIfNeeded(action, event);
|
||||
if (action.theme) {
|
||||
let themeToUse =
|
||||
action.theme === "<event>"
|
||||
? event.currentTarget.value
|
||||
: this.props.initialTheme || action.theme;
|
||||
this.props.setActiveTheme(themeToUse);
|
||||
window.AWSelectTheme(themeToUse);
|
||||
}
|
||||
|
||||
if (action.picker) {
|
||||
this.handlePickerAction(value);
|
||||
let options = props.content.tiles.data;
|
||||
options.forEach(opt => {
|
||||
if (opt.id === value) {
|
||||
AboutWelcomeUtils.handleUserAction(opt.action);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If the action has persistActiveTheme: true, we set the initial theme to the currently active theme
|
||||
@@ -759,10 +701,8 @@ export class WelcomeScreen extends React.PureComponent {
|
||||
setScreenMultiSelects={this.props.setScreenMultiSelects}
|
||||
activeMultiSelect={this.props.activeMultiSelect}
|
||||
setActiveMultiSelect={this.props.setActiveMultiSelect}
|
||||
activeSingleSelectSelections={this.props.activeSingleSelectSelections}
|
||||
setActiveSingleSelectSelection={
|
||||
this.props.setActiveSingleSelectSelection
|
||||
}
|
||||
activeSingleSelect={this.props.activeSingleSelect}
|
||||
setActiveSingleSelect={this.props.setActiveSingleSelect}
|
||||
totalNumberOfScreens={this.props.totalNumberOfScreens}
|
||||
appAndSystemLocaleInfo={this.props.appAndSystemLocaleInfo}
|
||||
negotiatedLanguage={this.props.negotiatedLanguage}
|
||||
|
||||
@@ -61,8 +61,8 @@ export const MultiStageProtonScreen = props => {
|
||||
setScreenMultiSelects={props.setScreenMultiSelects}
|
||||
activeMultiSelect={props.activeMultiSelect}
|
||||
setActiveMultiSelect={props.setActiveMultiSelect}
|
||||
activeSingleSelectSelections={props.activeSingleSelectSelections}
|
||||
setActiveSingleSelectSelection={props.setActiveSingleSelectSelection}
|
||||
activeSingleSelect={props.activeSingleSelect}
|
||||
setActiveSingleSelect={props.setActiveSingleSelect}
|
||||
totalNumberOfScreens={props.totalNumberOfScreens}
|
||||
handleAction={props.handleAction}
|
||||
isFirstScreen={props.isFirstScreen}
|
||||
|
||||
@@ -9,12 +9,11 @@ import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils.mjs";
|
||||
|
||||
// This component was formerly "Themes" and continues to support theme
|
||||
export const SingleSelect = ({
|
||||
activeSingleSelectSelections = {}, // This now holds all active selections keyed by `singleSelectId`
|
||||
activeSingleSelect,
|
||||
activeTheme,
|
||||
content,
|
||||
handleAction,
|
||||
setActiveSingleSelectSelection,
|
||||
singleSelectId,
|
||||
setActiveSingleSelect,
|
||||
}) => {
|
||||
const category = content.tiles?.category?.type || content.tiles?.type;
|
||||
const isSingleSelect = category === "single-select";
|
||||
@@ -49,12 +48,10 @@ export const SingleSelect = ({
|
||||
// When screen renders for first time or user navigates back, update state to
|
||||
// check default option.
|
||||
useEffect(() => {
|
||||
if (isSingleSelect && !activeSingleSelectSelections[singleSelectId]) {
|
||||
if (isSingleSelect && !activeSingleSelect) {
|
||||
let newActiveSingleSelect =
|
||||
content.tiles?.selected || content.tiles?.data[0].id;
|
||||
|
||||
setActiveSingleSelectSelection(newActiveSingleSelect, singleSelectId);
|
||||
|
||||
setActiveSingleSelect(newActiveSingleSelect);
|
||||
let selectedTile = content.tiles?.data.find(
|
||||
opt => opt.id === newActiveSingleSelect
|
||||
);
|
||||
@@ -68,7 +65,7 @@ export const SingleSelect = ({
|
||||
handleAction({ currentTarget: { value: selectedTile.id } });
|
||||
}
|
||||
}
|
||||
}, [activeSingleSelectSelections]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const CONFIGURABLE_STYLES = [
|
||||
"background",
|
||||
@@ -82,7 +79,7 @@ export const SingleSelect = ({
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={`tiles-single-select-container`}>
|
||||
<div className="tiles-single-select-container">
|
||||
<div>
|
||||
<fieldset className={`tiles-single-select-section ${category}`}>
|
||||
<Localized text={content.subtitle}>
|
||||
@@ -106,13 +103,12 @@ export const SingleSelect = ({
|
||||
}
|
||||
const selected =
|
||||
(theme && theme === activeTheme) ||
|
||||
(isSingleSelect &&
|
||||
activeSingleSelectSelections[singleSelectId] === value);
|
||||
(isSingleSelect && activeSingleSelect === value);
|
||||
const valOrObj = val => (typeof val === "object" ? val : {});
|
||||
|
||||
const handleClick = evt => {
|
||||
if (isSingleSelect) {
|
||||
setActiveSingleSelectSelection(value, singleSelectId); // Update selection for the specific component
|
||||
setActiveSingleSelect(value);
|
||||
}
|
||||
handleAction(evt);
|
||||
};
|
||||
|
||||
@@ -316,11 +316,11 @@ const MultiStageAboutWelcome = props => {
|
||||
// multi select screen.
|
||||
const [activeMultiSelects, setActiveMultiSelects] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({});
|
||||
|
||||
// Save the active single select state for each screen as an object keyed
|
||||
// Save the active single select state for each screen as string value keyed
|
||||
// by screen id. Similar to above, this allows us to remember the state of
|
||||
// each screen's single select picker when navigating back and forth between
|
||||
// screens, and allows us to have multiple single selects on a screen.
|
||||
const [activeSingleSelectSelections, setActiveSingleSelectSelections] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({});
|
||||
// screens.
|
||||
const [activeSingleSelects, setActiveSingleSelects] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({});
|
||||
|
||||
// Get the active theme so the rendering code can make it selected
|
||||
// by default.
|
||||
@@ -382,18 +382,10 @@ const MultiStageAboutWelcome = props => {
|
||||
};
|
||||
});
|
||||
};
|
||||
const setActiveSingleSelectSelection = (valueOrFn, singleSelectId) => {
|
||||
setActiveSingleSelectSelections(prevState => {
|
||||
const currentScreenSelections = prevState[currentScreen.id] || {};
|
||||
return {
|
||||
...prevState,
|
||||
[currentScreen.id]: {
|
||||
...currentScreenSelections,
|
||||
[singleSelectId]: typeof valueOrFn === "function" ? valueOrFn(prevState[currentScreen.id]) : valueOrFn
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
const setActiveSingleSelect = valueOrFn => setActiveSingleSelects(prevState => ({
|
||||
...prevState,
|
||||
[currentScreen.id]: typeof valueOrFn === "function" ? valueOrFn(prevState[currentScreen.id]) : valueOrFn
|
||||
}));
|
||||
return index === order ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(WelcomeScreen, {
|
||||
key: currentScreen.id + order,
|
||||
id: currentScreen.id,
|
||||
@@ -417,8 +409,8 @@ const MultiStageAboutWelcome = props => {
|
||||
activeMultiSelect: activeMultiSelects[currentScreen.id],
|
||||
setActiveMultiSelect: setActiveMultiSelect,
|
||||
autoAdvance: currentScreen.auto_advance,
|
||||
activeSingleSelectSelections: activeSingleSelectSelections[currentScreen.id],
|
||||
setActiveSingleSelectSelection: setActiveSingleSelectSelection,
|
||||
activeSingleSelect: activeSingleSelects[currentScreen.id],
|
||||
setActiveSingleSelect: setActiveSingleSelect,
|
||||
negotiatedLanguage: negotiatedLanguage,
|
||||
langPackInstallPhase: langPackInstallPhase,
|
||||
forceHideStepsIndicator: currentScreen.force_hide_steps_indicator,
|
||||
@@ -560,52 +552,8 @@ class WelcomeScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCo
|
||||
data
|
||||
});
|
||||
}
|
||||
logTelemetry({
|
||||
value,
|
||||
event,
|
||||
source,
|
||||
props
|
||||
}) {
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, source, event.name);
|
||||
|
||||
// Send additional telemetry if a messaging surface like feature callout is
|
||||
// dismissed via the dismiss button. Other causes of dismissal will be
|
||||
// handled separately by the messaging surface's own code.
|
||||
if (value === "dismiss_button" && !event.name) {
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendDismissTelemetry(props.messageId, source);
|
||||
}
|
||||
}
|
||||
async handleMigrationIfNeeded(action, props) {
|
||||
const hasMigrate = a => a.type === "SHOW_MIGRATION_WIZARD" || a.type === "MULTI_ACTION" && a.data?.actions?.some(hasMigrate);
|
||||
if (hasMigrate(action)) {
|
||||
await window.AWWaitForMigrationClose();
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, "migrate_close");
|
||||
}
|
||||
}
|
||||
applyThemeIfNeeded(action, event) {
|
||||
if (!action.theme) {
|
||||
return;
|
||||
}
|
||||
const themeToUse = action.theme === "<event>" ? event.currentTarget.value : this.props.initialTheme || action.theme;
|
||||
this.props.setActiveTheme(themeToUse);
|
||||
window.AWSelectTheme(themeToUse);
|
||||
}
|
||||
handlePickerAction(value) {
|
||||
const tileGroups = Array.isArray(this.props.content.tiles) ? this.props.content.tiles : [this.props.content.tiles];
|
||||
for (const tile of tileGroups) {
|
||||
if (!tile?.data) {
|
||||
continue;
|
||||
}
|
||||
for (const opt of tile.data) {
|
||||
if (opt.id === value) {
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction(opt.action);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async handleAction(event) {
|
||||
const {
|
||||
let {
|
||||
props
|
||||
} = this;
|
||||
const value = event.currentTarget.value ?? event.currentTarget.getAttribute("value");
|
||||
@@ -616,30 +564,21 @@ class WelcomeScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCo
|
||||
action: event.action
|
||||
};
|
||||
}
|
||||
if (!targetContent) {
|
||||
if (!(targetContent && targetContent.action)) {
|
||||
return;
|
||||
}
|
||||
let action;
|
||||
if (Array.isArray(targetContent)) {
|
||||
for (const tile of targetContent) {
|
||||
const matchedTile = tile.data.find(t => t.id === value);
|
||||
if (matchedTile?.action) {
|
||||
action = matchedTile.action;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!targetContent.action) {
|
||||
return;
|
||||
} else {
|
||||
action = targetContent.action;
|
||||
}
|
||||
// Send telemetry before waiting on actions
|
||||
this.logTelemetry({
|
||||
value,
|
||||
event,
|
||||
source,
|
||||
props
|
||||
});
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, source, event.name);
|
||||
|
||||
// Send additional telemetry if a messaging surface like feature callout is
|
||||
// dismissed via the dismiss button. Other causes of dismissal will be
|
||||
// handled separately by the messaging surface's own code.
|
||||
if (value === "dismiss_button" && !event.name) {
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendDismissTelemetry(props.messageId, source);
|
||||
}
|
||||
let {
|
||||
action
|
||||
} = targetContent;
|
||||
action = JSON.parse(JSON.stringify(action));
|
||||
if (action.collectSelect) {
|
||||
this.setMultiSelectActions(action);
|
||||
@@ -668,13 +607,26 @@ class WelcomeScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCo
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction(action);
|
||||
}
|
||||
// Wait until migration closes to complete the action
|
||||
await this.handleMigrationIfNeeded(action, props);
|
||||
const hasMigrate = a => a.type === "SHOW_MIGRATION_WIZARD" || a.type === "MULTI_ACTION" && a.data?.actions?.some(hasMigrate);
|
||||
if (hasMigrate(action)) {
|
||||
await window.AWWaitForMigrationClose();
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, "migrate_close");
|
||||
}
|
||||
}
|
||||
|
||||
// A special tiles.action.theme value indicates we should use the event's value vs provided value.
|
||||
this.applyThemeIfNeeded(action, event);
|
||||
if (action.theme) {
|
||||
let themeToUse = action.theme === "<event>" ? event.currentTarget.value : this.props.initialTheme || action.theme;
|
||||
this.props.setActiveTheme(themeToUse);
|
||||
window.AWSelectTheme(themeToUse);
|
||||
}
|
||||
if (action.picker) {
|
||||
this.handlePickerAction(value);
|
||||
let options = props.content.tiles.data;
|
||||
options.forEach(opt => {
|
||||
if (opt.id === value) {
|
||||
_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction(opt.action);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If the action has persistActiveTheme: true, we set the initial theme to the currently active theme
|
||||
@@ -788,8 +740,8 @@ class WelcomeScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCo
|
||||
setScreenMultiSelects: this.props.setScreenMultiSelects,
|
||||
activeMultiSelect: this.props.activeMultiSelect,
|
||||
setActiveMultiSelect: this.props.setActiveMultiSelect,
|
||||
activeSingleSelectSelections: this.props.activeSingleSelectSelections,
|
||||
setActiveSingleSelectSelection: this.props.setActiveSingleSelectSelection,
|
||||
activeSingleSelect: this.props.activeSingleSelect,
|
||||
setActiveSingleSelect: this.props.setActiveSingleSelect,
|
||||
totalNumberOfScreens: this.props.totalNumberOfScreens,
|
||||
appAndSystemLocaleInfo: this.props.appAndSystemLocaleInfo,
|
||||
negotiatedLanguage: this.props.negotiatedLanguage,
|
||||
@@ -1006,8 +958,8 @@ const MultiStageProtonScreen = props => {
|
||||
setScreenMultiSelects: props.setScreenMultiSelects,
|
||||
activeMultiSelect: props.activeMultiSelect,
|
||||
setActiveMultiSelect: props.setActiveMultiSelect,
|
||||
activeSingleSelectSelections: props.activeSingleSelectSelections,
|
||||
setActiveSingleSelectSelection: props.setActiveSingleSelectSelection,
|
||||
activeSingleSelect: props.activeSingleSelect,
|
||||
setActiveSingleSelect: props.setActiveSingleSelect,
|
||||
totalNumberOfScreens: props.totalNumberOfScreens,
|
||||
handleAction: props.handleAction,
|
||||
isFirstScreen: props.isFirstScreen,
|
||||
@@ -2277,9 +2229,8 @@ const ContentTiles = props => {
|
||||
},
|
||||
activeTheme: props.activeTheme,
|
||||
handleAction: props.handleAction,
|
||||
activeSingleSelectSelections: props.activeSingleSelectSelections,
|
||||
setActiveSingleSelectSelection: props.setActiveSingleSelectSelection,
|
||||
singleSelectId: `single-select-${index}`
|
||||
activeSingleSelect: props.activeSingleSelect,
|
||||
setActiveSingleSelect: props.setActiveSingleSelect
|
||||
}), tile.type === "mobile_downloads" && tile.data && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MobileDownloads__WEBPACK_IMPORTED_MODULE_4__.MobileDownloads, {
|
||||
data: tile.data,
|
||||
handleAction: props.handleAction
|
||||
@@ -2579,13 +2530,11 @@ __webpack_require__.r(__webpack_exports__);
|
||||
|
||||
// This component was formerly "Themes" and continues to support theme
|
||||
const SingleSelect = ({
|
||||
activeSingleSelectSelections = {},
|
||||
// This now holds all active selections keyed by `singleSelectId`
|
||||
activeSingleSelect,
|
||||
activeTheme,
|
||||
content,
|
||||
handleAction,
|
||||
setActiveSingleSelectSelection,
|
||||
singleSelectId
|
||||
setActiveSingleSelect
|
||||
}) => {
|
||||
const category = content.tiles?.category?.type || content.tiles?.type;
|
||||
const isSingleSelect = category === "single-select";
|
||||
@@ -2612,9 +2561,9 @@ const SingleSelect = ({
|
||||
// When screen renders for first time or user navigates back, update state to
|
||||
// check default option.
|
||||
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
||||
if (isSingleSelect && !activeSingleSelectSelections[singleSelectId]) {
|
||||
if (isSingleSelect && !activeSingleSelect) {
|
||||
let newActiveSingleSelect = content.tiles?.selected || content.tiles?.data[0].id;
|
||||
setActiveSingleSelectSelection(newActiveSingleSelect, singleSelectId);
|
||||
setActiveSingleSelect(newActiveSingleSelect);
|
||||
let selectedTile = content.tiles?.data.find(opt => opt.id === newActiveSingleSelect);
|
||||
// If applicable, automatically trigger the action for the default
|
||||
// selected tile.
|
||||
@@ -2626,11 +2575,11 @@ const SingleSelect = ({
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [activeSingleSelectSelections]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const CONFIGURABLE_STYLES = ["background", "borderRadius", "height", "marginBlock", "marginInline", "paddingBlock", "paddingInline", "width"];
|
||||
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
|
||||
className: `tiles-single-select-container`
|
||||
className: "tiles-single-select-container"
|
||||
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("fieldset", {
|
||||
className: `tiles-single-select-section ${category}`
|
||||
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
|
||||
@@ -2652,11 +2601,11 @@ const SingleSelect = ({
|
||||
if (!isSingleSelect) {
|
||||
inputName = category === "theme" ? "theme" : id; // unique names per item are currently used in the wallpaper picker
|
||||
}
|
||||
const selected = theme && theme === activeTheme || isSingleSelect && activeSingleSelectSelections[singleSelectId] === value;
|
||||
const selected = theme && theme === activeTheme || isSingleSelect && activeSingleSelect === value;
|
||||
const valOrObj = val => typeof val === "object" ? val : {};
|
||||
const handleClick = evt => {
|
||||
if (isSingleSelect) {
|
||||
setActiveSingleSelectSelection(value, singleSelectId); // Update selection for the specific component
|
||||
setActiveSingleSelect(value);
|
||||
}
|
||||
handleAction(evt);
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ describe("ContentTiles component", () => {
|
||||
let wrapper;
|
||||
let handleAction;
|
||||
let setActiveMultiSelect;
|
||||
let setActiveSingleSelectSelection;
|
||||
let setActiveSingleSelect;
|
||||
let globals;
|
||||
|
||||
const CHECKLIST_TILE = {
|
||||
@@ -78,7 +78,7 @@ describe("ContentTiles component", () => {
|
||||
sandbox = sinon.createSandbox();
|
||||
handleAction = sandbox.stub();
|
||||
setActiveMultiSelect = sandbox.stub();
|
||||
setActiveSingleSelectSelection = sandbox.stub();
|
||||
setActiveSingleSelect = sandbox.stub();
|
||||
globals = new GlobalOverrider();
|
||||
globals.set({
|
||||
AWSendToDeviceEmailsSupported: () => Promise.resolve(),
|
||||
@@ -434,7 +434,7 @@ describe("ContentTiles component", () => {
|
||||
handleAction={() => {}}
|
||||
activeMultiSelect={null}
|
||||
setActiveMultiSelect={setActiveMultiSelect}
|
||||
setActiveSingleSelectSelection={setActiveSingleSelectSelection}
|
||||
setActiveSingleSelect={setActiveSingleSelect}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -655,140 +655,4 @@ describe("ContentTiles component", () => {
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it("should select defaults of single select tiles independently of one another", () => {
|
||||
const SINGLE_SELECT_1 = {
|
||||
type: "single-select",
|
||||
selected: "test1",
|
||||
data: [
|
||||
{
|
||||
id: "test1",
|
||||
label: {
|
||||
raw: "test1 label",
|
||||
},
|
||||
},
|
||||
{
|
||||
defaultValue: true,
|
||||
id: "test2",
|
||||
label: {
|
||||
raw: "test2 label",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const SINGLE_SELECT_2 = {
|
||||
type: "single-select",
|
||||
selected: "test4",
|
||||
data: [
|
||||
{
|
||||
id: "test3",
|
||||
label: {
|
||||
raw: "test3 label",
|
||||
},
|
||||
},
|
||||
{
|
||||
defaultValue: true,
|
||||
id: "test4",
|
||||
label: {
|
||||
raw: "test4 label",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const content = { tiles: [SINGLE_SELECT_1, SINGLE_SELECT_2] };
|
||||
wrapper = mount(
|
||||
<ContentTiles
|
||||
content={content}
|
||||
setActiveSingleSelectSelection={setActiveSingleSelectSelection}
|
||||
handleAction={handleAction}
|
||||
/>
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
sinon.assert.calledWithExactly(
|
||||
setActiveSingleSelectSelection.getCall(0),
|
||||
"test1",
|
||||
"single-select-0"
|
||||
);
|
||||
|
||||
sinon.assert.calledWithExactly(
|
||||
setActiveSingleSelectSelection.getCall(1),
|
||||
"test4",
|
||||
"single-select-1"
|
||||
);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it("should handle interactions with multiple single select tiles independently of one another", () => {
|
||||
const SINGLE_SELECT_1 = {
|
||||
type: "single-select",
|
||||
selected: "test1",
|
||||
data: [
|
||||
{
|
||||
id: "test1",
|
||||
label: {
|
||||
raw: "test1 label",
|
||||
},
|
||||
},
|
||||
{
|
||||
defaultValue: true,
|
||||
id: "test2",
|
||||
label: {
|
||||
raw: "test2 label",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const SINGLE_SELECT_2 = {
|
||||
type: "single-select",
|
||||
selected: "test4",
|
||||
data: [
|
||||
{
|
||||
id: "test3",
|
||||
label: {
|
||||
raw: "test3 label",
|
||||
},
|
||||
},
|
||||
{
|
||||
defaultValue: true,
|
||||
id: "test4",
|
||||
label: {
|
||||
raw: "test4 label",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const content = { tiles: [SINGLE_SELECT_1, SINGLE_SELECT_2] };
|
||||
wrapper = mount(
|
||||
<ContentTiles
|
||||
content={content}
|
||||
setActiveSingleSelectSelection={setActiveSingleSelectSelection}
|
||||
handleAction={handleAction}
|
||||
/>
|
||||
);
|
||||
|
||||
wrapper.update();
|
||||
|
||||
const tile2 = wrapper.find('input[value="test2"]');
|
||||
tile2.simulate("click");
|
||||
|
||||
sinon.assert.calledWithExactly(
|
||||
setActiveSingleSelectSelection.getCall(2),
|
||||
"test2",
|
||||
"single-select-0"
|
||||
);
|
||||
|
||||
const tile3 = wrapper.find('input[value="test3"]');
|
||||
tile3.simulate("click");
|
||||
|
||||
sinon.assert.calledWithExactly(
|
||||
setActiveSingleSelectSelection.getCall(3),
|
||||
"test3",
|
||||
"single-select-1"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -236,7 +236,6 @@ describe("MultiStageAboutWelcome module", () => {
|
||||
totalNumberOfScreens: 1,
|
||||
setScreenMultiSelects: sandbox.stub(),
|
||||
setActiveMultiSelect: sandbox.stub(),
|
||||
setActiveSingleSelectSelection: sandbox.stub(),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -473,7 +472,7 @@ describe("MultiStageAboutWelcome module", () => {
|
||||
},
|
||||
},
|
||||
navigate: sandbox.stub(),
|
||||
setActiveSingleSelectSelection: sandbox.stub(),
|
||||
setActiveSingleSelect: sandbox.stub(),
|
||||
setActiveMultiSelect: sandbox.stub(),
|
||||
setScreenMultiSelects: sandbox.stub(),
|
||||
};
|
||||
@@ -490,9 +489,7 @@ describe("MultiStageAboutWelcome module", () => {
|
||||
);
|
||||
});
|
||||
it("should preselect the active value if present", async () => {
|
||||
SINGLE_SELECT_SCREEN_PROPS.activeSingleSelectSelections = {
|
||||
"tile-0": ["test2"],
|
||||
};
|
||||
SINGLE_SELECT_SCREEN_PROPS.activeSingleSelect = "test2";
|
||||
const wrapper = mount(
|
||||
<WelcomeScreen {...SINGLE_SELECT_SCREEN_PROPS} />
|
||||
);
|
||||
@@ -645,14 +642,10 @@ describe("MultiStageAboutWelcome module", () => {
|
||||
};
|
||||
const finishStub = sandbox.stub(global, "AWFinish");
|
||||
const wrapper = mount(<WelcomeScreen {...SCREEN_PROPS} />);
|
||||
let telemetrySpy = sandbox.spy(
|
||||
AboutWelcomeUtils,
|
||||
"sendDismissTelemetry"
|
||||
);
|
||||
|
||||
wrapper.find(".dismiss-button").simulate("click");
|
||||
|
||||
assert.calledOnce(finishStub);
|
||||
assert.calledOnce(telemetrySpy);
|
||||
});
|
||||
it("should handle SHOW_FIREFOX_ACCOUNTS", () => {
|
||||
TEST_ACTION.type = "SHOW_FIREFOX_ACCOUNTS";
|
||||
@@ -1175,35 +1168,6 @@ describe("MultiStageAboutWelcome module", () => {
|
||||
assert.notCalled(telemetrySpy);
|
||||
globals.restore();
|
||||
});
|
||||
it("should handle action from matched tile in tiles array", () => {
|
||||
const TILE_ID = "test-tile-id";
|
||||
SCREEN_PROPS.content.tiles = [
|
||||
{
|
||||
data: [
|
||||
{
|
||||
id: TILE_ID,
|
||||
action: {
|
||||
type: "OPEN_URL",
|
||||
data: { args: "https://example.com" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const wrapper = mount(<WelcomeScreen {...SCREEN_PROPS} />);
|
||||
|
||||
wrapper.instance().handleAction({
|
||||
currentTarget: { value: TILE_ID },
|
||||
source: "test-source",
|
||||
name: "test-click",
|
||||
});
|
||||
|
||||
const [calledArg] = AboutWelcomeUtils.handleUserAction.firstCall.args;
|
||||
const url = new URL(calledArg.data.args);
|
||||
|
||||
assert.equal(calledArg.type, "OPEN_URL");
|
||||
assert.equal(url.hostname, "example.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#handleUserAction", () => {
|
||||
|
||||
Reference in New Issue
Block a user