Skip to content

Commit

Permalink
Add favorite shot promo card. (mozilla-services#4878)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenba committed Sep 20, 2018
1 parent 96b45af commit b932761
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 30 deletions.
11 changes: 8 additions & 3 deletions locales/en-US/server.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,17 @@ errorThirdPartyCookiesEnabled = If you took this shot and cannot delete it, you
## Shot Page New Feature Promotion Dialog.
# Note: If possible, choose a short translation to better fit into the card.
promoTitle = Take Note!
promoMessage = Updated editing tools let you crop, highlight, and even add text to your shot.
promoLink = Give them a try
promoCloseButton =
.title = Close notification
editorPromoTitle = Take Note!
editorPromoMessage = Updated editing tools let you crop, highlight, and even add text to your shot.
editorPromoCallToAction = Give them a try
favShotsPromoTitle = Favorite Shots!
favShotsPromoMessage = You can now sign in with Firefox Account to favorite your shots and save forever.
favShotPromoCallToAction = Give it a try!
## Annotations

annotationPenButton =
Expand Down
8 changes: 4 additions & 4 deletions server/src/pages/shot/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ function shouldShowPromo(model) {
return false;
}
let show = false;
const count = localStorage.hasSeenPromoDialog;
const count = localStorage.hasSeenEditorPromoDialog;
if (!count) {
localStorage.hasSeenPromoDialog = 1;
localStorage.hasSeenEditorPromoDialog = 1;
show = true;
} else if (count < 3) {
localStorage.hasSeenPromoDialog = parseInt(count, 10) + 1;
localStorage.hasSeenEditorPromoDialog = parseInt(count, 10) + 1;
show = true;
}
return show;
Expand Down Expand Up @@ -77,7 +77,7 @@ exports.launch = function(data) {
}
}
model.highlightEditButton = shouldHighlightEditIcon(model);
model.promoDialog = shouldShowPromo(model);
model.showEditorPromoDialog = shouldShowPromo(model);
if (firstSet) {
refreshHash();
}
Expand Down
14 changes: 14 additions & 0 deletions server/src/pages/shot/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ exports.createModel = function(req) {
const title = req.getText("shotPageTitle", {originalTitle: req.shot.title});
const enableAnnotations = req.config.enableAnnotations;
const isFxaAuthenticated = req.accountId && req.accountId === req.shot.accountId;
const promos = {
editor: {
title: req.getText("editorPromoTitle"),
message: req.getText("editorPromoMessage"),
callToAction: req.getText("editorPromoCallToAction"),
},
favShot: {
title: req.getText("favShotsPromoTitle"),
message: req.getText("favShotsPromoMessage"),
callToAction: req.getText("favShotPromoCallToAction"),
},
};
const serverPayload = {
title,
staticLink: req.staticLink,
Expand Down Expand Up @@ -42,6 +54,7 @@ exports.createModel = function(req) {
downloadUrl,
isMobile,
enableAnnotations,
promos,
};
const clientPayload = {
title,
Expand Down Expand Up @@ -74,6 +87,7 @@ exports.createModel = function(req) {
downloadUrl,
isMobile,
enableAnnotations,
promos,
};
if (serverPayload.expireTime !== null && Date.now() > serverPayload.expireTime) {
clientPayload.shot = {
Expand Down
23 changes: 9 additions & 14 deletions server/src/pages/shot/promo-dialog.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const React = require("react");
const PropTypes = require("prop-types");
const { Localized } = require("fluent-react/compat");
const sendEvent = require("../../browser-send-event.js");

exports.PromoDialog = class PromoDialog extends React.Component {
constructor(props) {
Expand All @@ -11,30 +10,26 @@ exports.PromoDialog = class PromoDialog extends React.Component {
render() {
if (this.props.display) {
return <div id="promo-dialog-panel" className="promo-panel default-color-scheme" >
<Localized id="promoCloseButton">
<a className="box-close" title="Close notification" onClick={this.closePanel.bind(this)}></a>
</Localized>
<Localized id="promoTitle">
<h4 className="title">Take Note!</h4>
</Localized>
<Localized id="promoMessage">
<p className="message">
Updated editing tools let you crop, highlight, and even add text to your shot.
</p>
</Localized>
<p className="message"><Localized id="promoLink"><span className="message-text">Give them a try</span></Localized></p>
<a className="box-close" title="Close notification" onClick={this.closePanel.bind(this)}></a>
<h4 className="title">{this.props.title}</h4>
<p className="message">
{this.props.message}
</p>
<p className="message"><span className="message-text">{this.props.callToAction}</span></p>
</div>;
}
return null;
}

closePanel(event) {
this.props.promoClose();
sendEvent("promo-closed");
}
};

exports.PromoDialog.propTypes = {
display: PropTypes.bool,
promoClose: PropTypes.func,
title: PropTypes.string,
message: PropTypes.string,
callToAction: PropTypes.string,
};
20 changes: 20 additions & 0 deletions server/src/pages/shot/shotpage-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,20 @@ const sendEvent = require("../../browser-send-event.js");
const { SignInButton } = require("../../signin-button.js");
const { Header } = require("../../header.js");
const { TimeDiff } = require("./time-diff");
const { PromoDialog } = require("./promo-dialog");

exports.ShotPageHeader = class ShotPageHeader extends React.Component {
constructor(props) {
super(props);
this.state = {
showPromo: false,
};
}

componentDidUpdate(prevProps) {
if (this.props.showPromo !== prevProps.showPromo) {
this.setState({showPromo: this.props.showPromo});
}
}

renderMyShotsText() {
Expand Down Expand Up @@ -90,10 +100,19 @@ exports.ShotPageHeader = class ShotPageHeader extends React.Component {
}

renderFxASignIn() {
let promo = null;
if (this.props.promo) {
promo = <PromoDialog
display={this.state.showPromo}
{...this.props.promo}
promoClose={this.props.closePromoCallback}/>;
}

return (
this.props.isOwner ?
<div className="shot-fxa-signin">
<SignInButton isAuthenticated={this.props.isFxaAuthenticated} initialPage={this.props.shot.id} />
{promo}
</div> : null
);
}
Expand Down Expand Up @@ -121,6 +140,7 @@ exports.ShotPageHeader.propTypes = {
shot: PropTypes.object,
isFxaAuthenticated: PropTypes.bool,
expireTime: PropTypes.number,
promo: PropTypes.object,
};

class EditableTitle extends React.Component {
Expand Down
43 changes: 34 additions & 9 deletions server/src/pages/shot/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,13 @@ class Body extends React.Component {
hidden: false,
closeBanner: false,
imageEditing: false,
showFavShotPromo: false,
};
}

componentDidMount() {
this.setState({highlightEditButton: this.props.highlightEditButton || this.props.promoDialog});
this.setState({promoDialog: this.props.promoDialog});
this.setState({highlightEditButton: this.props.highlightEditButton || this.props.showEditorPromoDialog});
this.setState({showEditorPromoDialog: this.props.showEditorPromoDialog});
}

doCloseBanner() {
Expand Down Expand Up @@ -341,10 +342,10 @@ class Body extends React.Component {
let editButton = null;
const highlight = this.state.highlightEditButton ? <div className="edit-highlight" onClick={ this.onClickEdit.bind(this) } onMouseOver={ this.onMouseOverHighlight.bind(this) } onMouseOut={ this.onMouseOutHighlight.bind(this) }></div> : null;
const activeFavClass = this.props.expireTime ? "" : "is-fav";
const shouldShow = this.props.isFxaAuthenticated ? "" : "hidden";

favoriteShotButton = <div className="favorite-shot-button"><Localized id="shotPagefavoriteButton">
<button className={`nav-button ${shouldShow} `} onClick={this.onClickFavorite.bind(this)}>
<button className="nav-button"
onClick={this.onClickFavorite.bind(this)}>
<span className={`icon-favorite favorite ${activeFavClass}`} ></span>
<Localized id="shotPageFavorite">
<span className={`favorite-text favorite ${activeFavClass} `}>Favorite</span>
Expand Down Expand Up @@ -377,7 +378,10 @@ class Body extends React.Component {
</Localized>
</button>
</Localized>
<PromoDialog promoClose={this.promoClose.bind(this)} display={this.state.promoDialog} />
<PromoDialog
promoClose={this.closeEditorPromo.bind(this)}
display={this.state.showEditorPromoDialog}
{...this.props.promos.editor} />
{ highlight }
</div> : null;
}
Expand All @@ -403,7 +407,10 @@ class Body extends React.Component {
{ renderGetFirefox ? this.renderFirefoxRequired() : null }
<div id="frame" className="inverse-color-scheme full-height column-space">
<ShotPageHeader isOwner={this.props.isOwner} isFxaAuthenticated={this.props.isFxaAuthenticated}
shot={this.props.shot} expireTime={this.props.expireTime}>
shot={this.props.shot} expireTime={this.props.expireTime}
promo={this.props.promos.favShot}
showPromo={this.state.showFavShotPromo}
closePromoCallback={this.closeFavShotPromo.bind(this)}>
{ favoriteShotButton }
{ editButton }
{ downloadButton }
Expand All @@ -419,10 +426,15 @@ class Body extends React.Component {
</reactruntime.BodyTemplate>);
}

promoClose() {
this.setState({promoDialog: false});
closeEditorPromo() {
this.setState({showEditorPromoDialog: false});
// set counter to max to stop showing notification again
localStorage.hasSeenPromoDialog = 3;
sendEvent("editor-promo-closed");
}

closeFavShotPromo() {
this.setState({showFavShotPromo: false});
}

onMouseOverHighlight() {
Expand Down Expand Up @@ -455,7 +467,7 @@ class Body extends React.Component {
}
// Close promo dialog if user clicked edit after seeing new edit tool promo
if (this.props.promoDialog) {
this.promoClose();
this.closeEditorPromo();
}
}

Expand Down Expand Up @@ -490,6 +502,14 @@ class Body extends React.Component {
}

onClickFavorite() {
if (!this.props.isFxaAuthenticated) {
this.setState({
showEditorPromoDialog: false,
showFavShotPromo: true,
});
return;
}

if (this.props.expireTime) {
sendEvent("set-favorite", "navbar");
const INDEFINITE = 0;
Expand All @@ -500,6 +520,11 @@ class Body extends React.Component {
}
}

onCloseFavShotPromo() {
this.setState({showFavShotPromo: false});
sendEvent("fav-shot-promo-closed");
}

onClickDownload() {
sendEvent("download", "navbar");
location.href = this.props.downloadUrl;
Expand Down
6 changes: 6 additions & 0 deletions static/css/frame.scss
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@
}
}

.shot-fxa-signin {
.promo-panel {
right: 10px;
}
}

.delete-confirmation-dialog {
&.right-align {
top: 88px;
Expand Down

0 comments on commit b932761

Please sign in to comment.