Skip to content
Merged
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
57 changes: 45 additions & 12 deletions src/disco/components/Addon.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import { connect } from 'react-redux';
import { compose } from 'redux';

import { sanitizeHTML } from 'core/utils';
import translate from 'core/i18n/translate';
import themeAction from 'core/themePreview';
import tracking, { getAction } from 'core/tracking';
import InstallButton from 'core/components/InstallButton';
import AddonCompatibilityError from 'disco/components/AddonCompatibilityError';
import HoverIntent from 'core/components/HoverIntent';
import InstallButton from 'core/components/InstallButton';
import {
CLICK_CATEGORY,
DOWNLOAD_FAILED,
Expand All @@ -28,17 +25,27 @@ import {
validAddonTypes,
validInstallStates,
} from 'core/constants';
import translate from 'core/i18n/translate';
import { withInstallHelpers } from 'core/installAddon';
import themeAction from 'core/themePreview';
import tracking, { getAction } from 'core/tracking';
import {
getClientCompatibility as _getClientCompatibility,
sanitizeHTML,
} from 'core/utils';

import 'disco/css/Addon.scss';


export class AddonBase extends React.Component {
static propTypes = {
addon: PropTypes.object.isRequired,
clientApp: PropTypes.string.isRequired,
description: PropTypes.string,
error: PropTypes.string,
heading: PropTypes.string.isRequired,
getBrowserThemeData: PropTypes.func.isRequired,
getClientCompatibility: PropTypes.func,
i18n: PropTypes.object.isRequired,
iconUrl: PropTypes.string,
installTheme: PropTypes.func.isRequired,
Expand All @@ -50,13 +57,15 @@ export class AddonBase extends React.Component {
setCurrentStatus: PropTypes.func.isRequired,
status: PropTypes.oneOf(validInstallStates).isRequired,
type: PropTypes.oneOf(validAddonTypes).isRequired,
userAgentInfo: PropTypes.object.isRequired,
_tracking: PropTypes.object,
}

static defaultProps = {
getClientCompatibility: _getClientCompatibility,
needsRestart: false,
// Defaults themeAction to the imported func.
themeAction,
needsRestart: false,
_tracking: tracking,
}

Expand Down Expand Up @@ -117,14 +126,17 @@ export class AddonBase extends React.Component {
const { i18n, description, type } = this.props;
if (type === ADDON_TYPE_THEME) {
return (
<p className="editorial-description">{i18n.gettext('Hover over the image to preview')}</p>
<p className="editorial-description">
{i18n.gettext('Hover over the image to preview')}
</p>
);
}
return (
<div
ref={(ref) => { this.editorialDescription = ref; }}
className="editorial-description"
dangerouslySetInnerHTML={sanitizeHTML(description, ['blockquote', 'cite'])}
dangerouslySetInnerHTML={
sanitizeHTML(description, ['blockquote', 'cite'])
}
/>
);
}
Expand Down Expand Up @@ -188,7 +200,14 @@ export class AddonBase extends React.Component {
}

render() {
const { heading, type } = this.props;
const {
addon,
clientApp,
getClientCompatibility,
heading,
type,
userAgentInfo,
} = this.props;

if (!validAddonTypes.includes(type)) {
throw new Error(`Invalid addon type "${type}"`);
Expand All @@ -199,6 +218,9 @@ export class AddonBase extends React.Component {
extension: type === ADDON_TYPE_EXTENSION,
});

const { compatible, minVersion, reason } = getClientCompatibility({
addon, clientApp, userAgentInfo });

return (
// Disabling this is fine since the onClick is just being used to delegate
// click events bubbling from the link within the header.
Expand All @@ -218,14 +240,23 @@ export class AddonBase extends React.Component {
<div className="copy">
<h2
onClick={this.clickHeadingLink}
ref={(ref) => { this.heading = ref; }}
className="heading"
dangerouslySetInnerHTML={sanitizeHTML(heading, ['a', 'span'])}
/>
{this.getDescription()}
</div>
<InstallButton className="Addon-install-button" size="small" {...this.props} />
<InstallButton
className="Addon-install-button"
size="small"
{...this.props}
/>
</div>
{!compatible ? (
<AddonCompatibilityError
minVersion={minVersion}
reason={reason}
/>
) : null}
</div>
);
}
Expand All @@ -238,6 +269,8 @@ export function mapStateToProps(state, ownProps) {
addon,
...addon,
...installation,
clientApp: state.api.clientApp,
userAgentInfo: state.api.userAgentInfo,
};
}

Expand Down
68 changes: 68 additions & 0 deletions src/disco/components/AddonCompatibilityError/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* eslint-disable react/no-danger */
import React, { PropTypes } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';

import {
INCOMPATIBLE_FIREFOX_FOR_IOS,
INCOMPATIBLE_UNDER_MIN_VERSION,
} from 'core/constants';
import translate from 'core/i18n/translate';
import { sanitizeHTML } from 'core/utils';

import './style.scss';


// Messages in the disco pane are a bit less specific as we don't care about
// non-Firefox clients and the copy space is limited.
export class AddonCompatibilityErrorBase extends React.Component {
static propTypes = {
i18n: PropTypes.object.isRequired,
minVersion: PropTypes.string.isRequired,
reason: PropTypes.string.isRequired,
}

render() {
const {
i18n,
minVersion,
reason,
} = this.props;
let message;

if (typeof reason === 'undefined') {
throw new Error('AddonCompatibilityError requires a "reason" prop');
}
if (typeof minVersion === 'undefined') {
throw new Error('minVersion is required; it cannot be undefined');
}

if (reason === INCOMPATIBLE_FIREFOX_FOR_IOS) {
message = i18n.gettext(
'Firefox for iOS does not currently support add-ons.');
} else if (reason === INCOMPATIBLE_UNDER_MIN_VERSION) {
message = i18n.gettext(
'This add-on does not support your version of Firefox.');
} else {
// Unknown reasons are fine on the Disco Pane because we don't
// care about non-FF clients.
message = i18n.gettext('This add-on does not support your browser.');
}

return (
<div
className="AddonCompatibilityError"
dangerouslySetInnerHTML={sanitizeHTML(message, ['a'])}
/>
);
}
}

export function mapStateToProps(state) {
return { lang: state.api.lang };
}

export default compose(
connect(mapStateToProps),
translate({ withRef: true }),
)(AddonCompatibilityErrorBase);
16 changes: 16 additions & 0 deletions src/disco/components/AddonCompatibilityError/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@import "~ui/css/vars";

.AddonCompatibilityError {
background: $report-base-color;
font-size: 12px;
margin: 0;
padding: 5px;
text-align: center;
width: 100%;

&,
a,
a:link {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any other states needed e.g: visited, hover, focus, active etc or are the defaults ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The defaults are fine, this just keeps the colour white which it will stay for those other states too.

color: $white;
}
}
9 changes: 8 additions & 1 deletion src/disco/css/Addon.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ $addon-padding: 20px;
border-radius: 3px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.4);
display: flex;
flex-direction: row;
flex-flow: row wrap;
line-height: 1.5;
margin-top: 20px;

Expand Down Expand Up @@ -53,6 +53,11 @@ $addon-padding: 20px;
}
}

.InstallButton,
.InstallButton--disabled {
margin: 0 20px 10px;
}

&:not(.theme) .Addon-install-button {
> .switch {
float: right;
Expand All @@ -68,6 +73,7 @@ $addon-padding: 20px;
align-self: stretch;
display: flex;
padding: 0 10px;
width: 94px;

img {
display: block;
Expand Down Expand Up @@ -151,6 +157,7 @@ $addon-padding: 20px;
&:not(.theme) .content {
flex-direction: column;
align-items: left;
width: calc(100% - 94px);
}

@include respond-to(large) {
Expand Down
4 changes: 0 additions & 4 deletions src/disco/css/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,3 @@ header {
}
}
}

.InstallButton {
@include padding-end(20px);
}
6 changes: 6 additions & 0 deletions src/ui/css/vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,9 @@ $font-size-m: 18px;
$font-size-l: 24px;
$font-size-xl: 36px;
$font-size-xxl: 42px;

// Border radius sizes
// Border-Radius Variables
$border-radius-default: 9px;
$border-radius-s: 4px;
$border-radius-m: 8px;
Loading