diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 344314d05..72acad9af 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -2143,5 +2143,25 @@ }, "new_color_themes": { "message": "New Color Themes" + }, + "upgrade_cta_TEXT": { + "message": "Unlock historical tracker insights, priority support access, and new color themes by upgrading to Ghostery Plus for only $2 per month.", + "description": "Body text in a non-responsive modal. Character limit: 135." + }, + "upgrade_your_ghostery_experience": { + "message": "Upgrade your Ghostery experience", + "description": "Header text for a non-responsive modal. Character limit: 40." + }, + "upgrade_to_plus": { + "message": "Upgrade to Plus", + "description": "Button text in a non-responsive modal. Character limit: 35." + }, + "no_thanks_turn_promos_off": { + "message": "No thanks, turn promos off", + "description": "Text link in a non-responsive modal. Character limit: 28." + }, + "already_subscribed_sign_in": { + "message": "Already subscribed? Sign In", + "description": "Character limit: 28." } } diff --git a/app/images/hub/home/gold-ghostie-badge.svg b/app/images/hub/home/gold-ghostie-badge.svg new file mode 100644 index 000000000..a6cba7a4d --- /dev/null +++ b/app/images/hub/home/gold-ghostie-badge.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/panel/components/BuildingBlocks/PanelToTabLink.jsx b/app/panel/components/BuildingBlocks/PanelToTabLink.jsx index 32748e1b1..286827c53 100644 --- a/app/panel/components/BuildingBlocks/PanelToTabLink.jsx +++ b/app/panel/components/BuildingBlocks/PanelToTabLink.jsx @@ -19,10 +19,12 @@ import { handleClickOnNewTabLink } from '../../utils/msg'; * @memberof PanelBuildingBlocks */ const PanelToTabLink = (props) => { - const { href, children } = props; + const { className, href, children } = props; + + const classes = className || ''; return ( - {children} + {children} ); }; diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index c835e73d1..bf5cac120 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -14,6 +14,7 @@ import React from 'react'; import ClassNames from 'classnames'; import Header from '../containers/HeaderContainer'; +import PanelToTabLink from './BuildingBlocks/PanelToTabLink'; import { PlusPromoModal, Modal } from '../../shared-components'; import InsightsPromoModal from '../containers/InsightsPromoModalContainer'; import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; @@ -208,21 +209,60 @@ class Panel extends React.Component { }); } - _renderPlusPromoUpgradeModal() { + _handleNoThanksClick = () => { + sendMessage('promoModals.sawPlusPromo', {}); + sendMessage('promoModals.turnOffPromos', {}); + this.setState({ + plusPromoModalShown: true + }); + } + + _handleSubscriberSignInClick = () => { + sendMessage('promoModals.sawPlusPromo', {}); + this.setState({ + plusPromoModalShown: true + }); + this.props.history.push('/login'); + } + + _renderPlusPromoUpgradeModal(signedIn) { const contentClassNames = ClassNames( 'PlusPromoModal__content', 'flex-container', 'flex-dir-column', 'align-middle', - 'panel' + 'panel', + 'upgrade' ); return (
-
[Upgrade version of the Plus Promo modal]
-
- Dismiss +
+ +
+ {t('upgrade_your_ghostery_experience')} +
+
+ {t('upgrade_cta_TEXT')} +
+
+ + {t('upgrade_to_plus')} + +
+
+ { + !signedIn && + ( +
+ {t('already_subscribed_sign_in')} +
+ ) + } +
+ {t('no_thanks_turn_promos_off')} +
@@ -233,12 +273,17 @@ class Panel extends React.Component { const { plusPromoModalShown } = this.state; const { account, haveSeenInitialPlusPromo, isTimeForAPlusPromo } = this.props; - if (account && account.user && account.user.subscriptionsPlus) return null; // don't show the promo to Plus subscribers! - if (account && account.user && account.user.scopes && account.user.scopes.includes('subscriptions:insights')) return null; // don't show the promo to Insights subscribers, either - + // The business logic that controls how often promo modals should be shown lives in src/classes/PromoModals if (plusPromoModalShown || !isTimeForAPlusPromo) return null; - if (haveSeenInitialPlusPromo) { return this._renderPlusPromoUpgradeModal(); } + // Check account status + const signedIn = account && account.user; + const plusSubscriber = signedIn && account.user.subscriptionsPlus; + const insightsSubscriber = signedIn && account.user.scopes && account.user.scopes.includes('subscriptions:insights'); + + if (plusSubscriber || insightsSubscriber) return null; + + if (haveSeenInitialPlusPromo) { return this._renderPlusPromoUpgradeModal(signedIn); } return ( {
{(loggedIn === 'false') && ( - {t('subscribe_pitch_sign_here')} + {t('already_subscribed_sign_in')} )}
diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx index 4b55a6bba..ecfe82dd2 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx @@ -31,6 +31,7 @@ function _renderInitialVersion(props) { 'flex-container', 'flex-dir-column', 'align-middle', + 'initial', locationClassName ); const optionsContainerClassNames = ClassNames( @@ -55,7 +56,7 @@ function _renderInitialVersion(props) { return (
-
+
{isInHub && (
{t('thanks_for_downloading_ghostery')} @@ -81,7 +82,7 @@ function _renderInitialVersion(props) {
{t('fast_browsing')}
-
+
{t('select_basic')}
@@ -114,7 +115,7 @@ function _renderInitialVersion(props) {
- + {t('select_plus')} diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.scss b/app/shared-components/PlusPromoModal/PlusPromoModal.scss index 7aea1c077..310d80ac7 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.scss +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.scss @@ -1,17 +1,47 @@ +$standard-font-family: Roboto, "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + +.PlusPromoModal__gold-ghostie-badge { + margin-top: 21px; + margin-bottom: 16px; +} + +.PlusPromoModal__header { + margin-bottom: 10px; + font-size: 20px; + font-weight: bold; + font-family: $standard-font-family; +} + +.PlusPromoModal__description { + margin-bottom: 5px; + width: 350px; + text-align: center; + font-size: 18px; + font-weight: 500; + font-family: $standard-font-family +} + .PlusPromoModal__content { position: relative; background-color: #f7f7f7; border: 1.9px solid #930194; z-index: 10; - &.in-hub { - width: 646px; - height: 553px; + &.initial { + &.in-hub { + width: 646px; + height: 553px; + } + + &.in-panel { + width: 556px; + height: 471px; + } } - &.in-panel { - width: 556px; - height: 471px; + &.upgrade { + width: 434px; + height: 410px; } } @@ -22,6 +52,9 @@ width: 99%; height: 72px; z-index: -1; + + &.initial { height: 72px; } + &.upgrade { height: 107px; } } .PlusPromoModal__thanks-for-download { @@ -162,23 +195,35 @@ justify-content: center; } +.PlusPromoModal__button-container { + width: 100%; + display: flex; + justify-content: center; + position: absolute; + bottom: 50px; +} + .PlusPromoModal__button { - margin: 0; - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; + border-radius: 3px; display: flex; - align-items: center; justify-content: center; - box-shadow: none; + align-items: center; + font-weight: bold; + font-family: $standard-font-family; + letter-spacing: 0.5px; + text-transform: uppercase; + cursor: pointer; + transition: background-color 0.25s ease-out, color 0.25s ease-out; + -webkit-appearance: none; &.basic { + font-size: 11px; width: 135px; height: 40px; border: solid 2px #15b4f2; background-color: white; color: #2cbcf4; + box-shadow: none; } &.basic:hover { background-color: #2cbcf4; @@ -186,15 +231,50 @@ } &.plus { + font-size: 11px; width: 163px; height: 38px; border: none; background-image: linear-gradient(to bottom, #2fdbfa, #15b4f2); color: white; - font-weight: 600; - letter-spacing: 0.5px; + box-shadow: none; } &.plus:hover { background-image: linear-gradient(to bottom, #1fcbea, #05a4e2); } + + &.upgrade { + font-size: 13px; + height: 36px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.24), 0 0 2px 0 rgba(0, 0, 0, 0.12); + background-color: #1dafed; + color: white; + } + &.upgrade:hover { + background-color: #0698d6; + } + + .button-text { + padding: 0px 20px 0px; + color: white; + text-decoration: none; + } +} + +.PlusPromoModal__text-link-container { + position: absolute; + bottom: 10px; + width: 100%; + display: flex; + justify-content: space-evenly; +} + +.PlusPromoModal__text-link { + margin-left: 10px; + margin-right: 10px; + font-size: 15px; + font-family: $standard-font-family; + color: #4a4a4a; + text-decoration: underline; + cursor: pointer; } diff --git a/src/background.js b/src/background.js index 0ee925611..9b9a272d5 100644 --- a/src/background.js +++ b/src/background.js @@ -1086,6 +1086,10 @@ function onMessageHandler(request, sender, callback) { promoModals.recordInsightsPromoSighting(); return true; } + if (name === 'promoModals.turnOffPromos') { + promoModals.turnOffPromos(); + return true; + } } /** diff --git a/src/classes/PromoModals.js b/src/classes/PromoModals.js index c068b2c84..5d4ab9ee0 100644 --- a/src/classes/PromoModals.js +++ b/src/classes/PromoModals.js @@ -41,6 +41,8 @@ class PromoModals { static recordInsightsPromoSighting() { this._recordPromoSighting(INSIGHTS); } + static turnOffPromos() { conf.notify_promotions = false; } + static _isTimeForAPromo(type) { if (conf.notify_promotions === false) { return false; }