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

Frontend Compatibility for Multiple Promoted Addon Groups #13343

Merged
merged 23 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
20 changes: 12 additions & 8 deletions src/amo/components/AddonBadges/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { compose } from 'redux';

import { CLIENT_APP_FIREFOX } from 'amo/constants';
import translate from 'amo/i18n/translate';
import { getPromotedCategory } from 'amo/utils/addons';
import { getPromotedCategories } from 'amo/utils/addons';
import Badge from 'amo/components/Badge';
import PromotedBadge from 'amo/components/PromotedBadge';
import type { AppState } from 'amo/store';
Expand All @@ -19,7 +19,7 @@ type Props = {|
|};

type DefaultProps = {|
_getPromotedCategory: typeof getPromotedCategory,
_getPromotedCategories: typeof getPromotedCategories,
|};

type PropsFromState = {|
Expand All @@ -35,27 +35,31 @@ type InternalProps = {|

export class AddonBadgesBase extends React.Component<InternalProps> {
static defaultProps: DefaultProps = {
_getPromotedCategory: getPromotedCategory,
_getPromotedCategories: getPromotedCategories,
};

render(): null | React.Node {
const { _getPromotedCategory, addon, clientApp, i18n } = this.props;
const { _getPromotedCategories, addon, clientApp, i18n } = this.props;

if (!addon) {
return null;
}

const promotedCategory = _getPromotedCategory({
const promotedCategories = _getPromotedCategories({
addon,
clientApp,
forBadging: true,
});

return (
<div className="AddonBadges">
chrstinalin marked this conversation as resolved.
Show resolved Hide resolved
{promotedCategory ? (
<PromotedBadge category={promotedCategory} size="large" />
) : null}
{promotedCategories.map((category) => (
<PromotedBadge
key={`${addon.name}-${category}`}
category={category}
size="large"
/>
))}
{addon.is_experimental ? (
<Badge type="experimental" label={i18n.gettext('Experimental')} />
) : null}
Expand Down
2 changes: 1 addition & 1 deletion src/amo/components/AutoSearchInput/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export class AutoSearchInputBase extends React.Component<InternalProps, State> {
addonId: undefined,
iconUrl: getAddonIconUrl(),
name: this.props.i18n.gettext('Loading'),
promoted: null,
promoted: [],
url: undefined,
});
}
Expand Down
18 changes: 10 additions & 8 deletions src/amo/components/HeroRecommendation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
import translate from 'amo/i18n/translate';
import log from 'amo/logger';
import tracking from 'amo/tracking';
import { getPromotedCategory } from 'amo/utils/addons';
import { getPromotedCategories } from 'amo/utils/addons';
import { addQueryParams } from 'amo/utils/url';
import LoadingText from 'amo/components/LoadingText';
import type { PrimaryHeroShelfType } from 'amo/reducers/home';
Expand Down Expand Up @@ -53,7 +53,7 @@ export type PropsFromState = {|

export type DefaultProps = {|
_checkInternalURL: typeof checkInternalURL,
_getPromotedCategory: typeof getPromotedCategory,
_getPromotedCategories: typeof getPromotedCategories,
_tracking: typeof tracking,
|};

Expand All @@ -67,7 +67,7 @@ export type InternalProps = {|
export class HeroRecommendationBase extends React.Component<InternalProps> {
static defaultProps: DefaultProps = {
_checkInternalURL: checkInternalURL,
_getPromotedCategory: getPromotedCategory,
_getPromotedCategories: getPromotedCategories,
_tracking: tracking,
};

Expand Down Expand Up @@ -142,7 +142,7 @@ export class HeroRecommendationBase extends React.Component<InternalProps> {
render(): null | React.Node {
const {
_checkInternalURL,
_getPromotedCategory,
_getPromotedCategories,
clientApp,
i18n,
errorHandler,
Expand Down Expand Up @@ -219,17 +219,17 @@ export class HeroRecommendationBase extends React.Component<InternalProps> {
// L10n: If uppercase does not work in your locale, change it to lowercase. This is used as a secondary heading.
let titleText = null;

const promotedCategory = _getPromotedCategory({
const promotedCategories = _getPromotedCategories({
addon,
clientApp,
forBadging: true,
});

if (!loading) {
if (promotedCategory === RECOMMENDED) {
if (promotedCategories.includes(RECOMMENDED)) {
// L10n: If uppercase does not work in your locale, change it to lowercase. This is used as a secondary heading.
titleText = i18n.gettext('RECOMMENDED');
} else if (promotedCategory === LINE) {
} else if (promotedCategories.includes(LINE)) {
// L10n: If uppercase does not work in your locale, change it to lowercase. This is used as a secondary heading.
titleText = i18n.gettext('BY FIREFOX');
} else {
Expand All @@ -242,7 +242,9 @@ export class HeroRecommendationBase extends React.Component<InternalProps> {
<div className="HeroRecommendation-title-text">
{titleText || <LoadingText width={20} />}
</div>
{![LINE, RECOMMENDED].includes(promotedCategory) && !loading ? (
{![LINE, RECOMMENDED].some((item) =>
chrstinalin marked this conversation as resolved.
Show resolved Hide resolved
promotedCategories.includes(item),
) && !loading ? (
<a
className="HeroRecommendation-title-link"
href={`${getPromotedBadgesLinkUrl({
Expand Down
15 changes: 8 additions & 7 deletions src/amo/components/InstallWarning/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
EXCLUDE_WARNING_CATEGORIES,
} from 'amo/constants';
import translate from 'amo/i18n/translate';
import { getPromotedCategory } from 'amo/utils/addons';
import { getPromotedCategories } from 'amo/utils/addons';
import {
correctedLocationForPlatform,
isFirefox,
Expand All @@ -36,7 +36,7 @@ type PropsFromState = {|

type DefaultProps = {|
_correctedLocationForPlatform: typeof correctedLocationForPlatform,
_getPromotedCategory: typeof getPromotedCategory,
_getPromotedCategories: typeof getPromotedCategories,
|};

type InternalProps = {|
Expand All @@ -55,13 +55,13 @@ const WARNING_LINK_DESTINATION = getPromotedBadgesLinkUrl({
export class InstallWarningBase extends React.Component<InternalProps> {
static defaultProps: DefaultProps = {
_correctedLocationForPlatform: correctedLocationForPlatform,
_getPromotedCategory: getPromotedCategory,
_getPromotedCategories: getPromotedCategories,
};

couldShowWarning: () => boolean = () => {
const {
_correctedLocationForPlatform,
_getPromotedCategory,
_getPromotedCategories,
addon,
clientApp,
lang,
Expand All @@ -77,7 +77,7 @@ export class InstallWarningBase extends React.Component<InternalProps> {
userAgentInfo,
});

const promotedCategory = _getPromotedCategory({
const promotedCategories = _getPromotedCategories({
addon,
clientApp,
});
Expand All @@ -86,8 +86,9 @@ export class InstallWarningBase extends React.Component<InternalProps> {
!correctedLocation &&
isFirefox({ userAgentInfo }) &&
addon.type === ADDON_TYPE_EXTENSION &&
(!promotedCategory ||
!EXCLUDE_WARNING_CATEGORIES.includes(promotedCategory))
promotedCategories.every(
(promoted) => !EXCLUDE_WARNING_CATEGORIES.includes(promoted),
)
);
};

Expand Down
29 changes: 16 additions & 13 deletions src/amo/components/SearchResult/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from 'amo/constants';
import translate from 'amo/i18n/translate';
import { getAddonIconUrl, getPreviewImage } from 'amo/imageUtils';
import { getPromotedCategory } from 'amo/utils/addons';
import { getPromotedCategories } from 'amo/utils/addons';
import { addQueryParams } from 'amo/utils/url';
import Icon from 'amo/components/Icon';
import LoadingText from 'amo/components/LoadingText';
Expand Down Expand Up @@ -52,17 +52,17 @@ type PropsFromState = {|
type InternalProps = {|
...Props,
...PropsFromState,
_getPromotedCategory: typeof getPromotedCategory,
_getPromotedCategories: typeof getPromotedCategories,
history: ReactRouterHistoryType,
i18n: I18nType,
|};

export class SearchResultBase extends React.Component<InternalProps> {
static defaultProps: {|
...DefaultProps,
_getPromotedCategory: typeof getPromotedCategory,
_getPromotedCategories: typeof getPromotedCategories,
|} = {
_getPromotedCategory: getPromotedCategory,
_getPromotedCategories: getPromotedCategories,
showFullSizePreview: false,
showMetadata: true,
showPromotedBadge: true,
Expand Down Expand Up @@ -98,7 +98,7 @@ export class SearchResultBase extends React.Component<InternalProps> {

renderResult(): React.Node {
const {
_getPromotedCategory,
_getPromotedCategories,
addon,
addonInstallSource,
clientApp,
Expand Down Expand Up @@ -172,7 +172,7 @@ export class SearchResultBase extends React.Component<InternalProps> {
summary = <p className="SearchResult-summary" {...summaryProps} />;
}

const promotedCategory = _getPromotedCategory({
const promotedCategories = _getPromotedCategories({
addon,
clientApp,
forBadging: true,
Expand Down Expand Up @@ -200,13 +200,16 @@ export class SearchResultBase extends React.Component<InternalProps> {
<div className="SearchResult-contents">
<h2 className="SearchResult-name">
{addonTitle}
{showPromotedBadge && addon && promotedCategory ? (
<PromotedBadge
category={promotedCategory}
onClick={(e) => e.stopPropagation()}
size="small"
/>
) : null}
{showPromotedBadge && addon
? promotedCategories.map((category) => (
<PromotedBadge
key={`${addon.name}-${category}`}
category={category}
onClick={(e) => e.stopPropagation()}
size="small"
/>
))
: null}
</h2>
{summary}

Expand Down
15 changes: 8 additions & 7 deletions src/amo/components/SearchSuggestion/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as React from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux';

import { getPromotedCategory } from 'amo/utils/addons';
import { getPromotedCategories } from 'amo/utils/addons';
import Icon from 'amo/components/Icon';
import IconPromotedBadge from 'amo/components/IconPromotedBadge';
import LoadingText from 'amo/components/LoadingText';
Expand All @@ -26,19 +26,19 @@ type PropsFromState = {|
type InternalProps = {|
...Props,
...PropsFromState,
_getPromotedCategory: typeof getPromotedCategory,
_getPromotedCategories: typeof getPromotedCategories,
|};

export const SearchSuggestionBase = ({
_getPromotedCategory = getPromotedCategory,
_getPromotedCategories = getPromotedCategories,
arrowAlt,
clientApp,
loading,
suggestion,
}: InternalProps): React.Node => {
const { iconUrl, name, type } = suggestion;

const promotedCategory = _getPromotedCategory({
const promotedCategories = _getPromotedCategories({
addon: suggestion,
clientApp,
forBadging: true,
Expand All @@ -52,14 +52,15 @@ export const SearchSuggestionBase = ({
<span className="SearchSuggestion-name">
{loading ? <LoadingText minWidth={20} /> : name}
</span>
{promotedCategory ? (
{promotedCategories.map((category) => (
<IconPromotedBadge
category={promotedCategory}
key={`${suggestion.name}-${category}`}
category={category}
className="SearchSuggestion-icon-promoted"
showAlt
size="small"
/>
) : null}
))}
<Icon
alt={arrowAlt}
className="SearchSuggestion-icon-arrow"
Expand Down
17 changes: 10 additions & 7 deletions src/amo/installAddon.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
import * as addonManager from 'amo/addonManager';
import { getVersionById } from 'amo/reducers/versions';
import { getDisplayName } from 'amo/utils';
import { getFileHash, getPromotedCategory } from 'amo/utils/addons';
import { getFileHash, getPromotedCategories } from 'amo/utils/addons';
import type { AppState } from 'amo/store';
import type { AddonVersionType } from 'amo/reducers/versions';
import type { AddonType } from 'amo/types/addons';
Expand Down Expand Up @@ -128,7 +128,7 @@ type WithInstallHelpersPropsFromState = {|

type WithInstallHelpersDefaultProps = {|
_addonManager: typeof addonManager,
_getPromotedCategory: typeof getPromotedCategory,
_getPromotedCategories: typeof getPromotedCategories,
_log: typeof log,
_tracking: typeof tracking,
|};
Expand Down Expand Up @@ -158,7 +158,7 @@ export type WithInstallHelpersInjectedProps = {|
export class WithInstallHelpers extends React.Component<WithInstallHelpersInternalProps> {
static defaultProps: WithInstallHelpersDefaultProps = {
_addonManager: addonManager,
_getPromotedCategory: getPromotedCategory,
_getPromotedCategories: getPromotedCategories,
_log: log,
_tracking: tracking,
};
Expand Down Expand Up @@ -269,7 +269,7 @@ export class WithInstallHelpers extends React.Component<WithInstallHelpersIntern
install(): Promise<void> {
const {
_addonManager,
_getPromotedCategory,
_getPromotedCategories,
_log,
_tracking,
addon,
Expand Down Expand Up @@ -329,10 +329,13 @@ export class WithInstallHelpers extends React.Component<WithInstallHelpersIntern

// If the add-on is trusted, send an additional event for trusted
// add-on install.
const promotedCategory = _getPromotedCategory({ addon, clientApp });
if (addon.type === ADDON_TYPE_EXTENSION && promotedCategory) {
const promotedCategories = _getPromotedCategories({ addon, clientApp });
if (
addon.type === ADDON_TYPE_EXTENSION &&
promotedCategories.length > 0
) {
_tracking.sendEvent({
action: promotedCategory,
action: promotedCategories.join(', '),
category: INSTALL_TRUSTED_EXTENSION_CATEGORY,
label: guid,
});
Expand Down
4 changes: 2 additions & 2 deletions src/amo/reducers/autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type ExternalSuggestion = {|
icon_url: string,
id: number,
name: LocalizedString,
promoted: PromotedType | null,
promoted: Array<PromotedType> | PromotedType | null,
type: string,
url: string,
|};
Expand All @@ -27,7 +27,7 @@ export type SuggestionType = {|
addonId: number,
iconUrl: string,
name: string,
promoted: PromotedType | null,
promoted: Array<PromotedType> | PromotedType | null,
chrstinalin marked this conversation as resolved.
Show resolved Hide resolved
type: string,
url: string,
|};
Expand Down
2 changes: 1 addition & 1 deletion src/amo/sagas/addons.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const makeNonPublicAddon = (slug: string): ExternalAddonType => {
},
// Assume extension.
type: ADDON_TYPE_EXTENSION,
promoted: null,
promoted: [],
created: new Date(0),
last_updated: null,
// Mark the add-on as non-public.
Expand Down
2 changes: 1 addition & 1 deletion src/amo/types/addons.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export type ExternalAddonType = {|
locale_disambiguation?: string,
name: LocalizedString,
previews?: Array<ExternalPreviewType>,
promoted: PromotedType | null,
promoted: Array<PromotedType> | PromotedType | null,
ratings: {|
average: number,
bayesian_average: number,
Expand Down
Loading
Loading