From 2d4ee04e874e4420aa940c148c77c977188b9500 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Mon, 25 Feb 2019 16:34:18 +0100 Subject: Add dialog to share franz on social media --- src/features/basicAuth/Component.js | 1 + src/features/basicAuth/index.js | 3 +- src/features/delayApp/index.js | 6 +- src/features/shareFranz/Component.js | 160 +++++++++++++++++++++++++++++++++++ src/features/shareFranz/index.js | 52 ++++++++++++ 5 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 src/features/shareFranz/Component.js create mode 100644 src/features/shareFranz/index.js (limited to 'src/features') diff --git a/src/features/basicAuth/Component.js b/src/features/basicAuth/Component.js index 13395fb40..a8252acb7 100644 --- a/src/features/basicAuth/Component.js +++ b/src/features/basicAuth/Component.js @@ -62,6 +62,7 @@ export default @injectSheet(styles) @observer class BasicAuthModal extends Compo isOpen={isModalVisible} className={classes.modal} close={this.cancel.bind(this)} + showClose={false} >

Sign in

diff --git a/src/features/basicAuth/index.js b/src/features/basicAuth/index.js index 00ad65ce6..89607824b 100644 --- a/src/features/basicAuth/index.js +++ b/src/features/basicAuth/index.js @@ -6,7 +6,7 @@ import BasicAuthComponent from './Component'; const debug = require('debug')('Franz:feature:basicAuth'); const defaultState = { - isModalVisible: false, + isModalVisible: true, service: null, authInfo: null, }; @@ -15,7 +15,6 @@ export const state = observable(defaultState); export function resetState() { Object.assign(state, defaultState); - console.log('reset state', state); } export default function initialize() { diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js index 48aac34b6..abc8274cf 100644 --- a/src/features/delayApp/index.js +++ b/src/features/delayApp/index.js @@ -28,8 +28,12 @@ export default function init(stores) { let shownAfterLaunch = false; let timeLastDelay = moment(); + window.franz.features.delayApp = { + state, + }; + reaction( - () => stores.features.features.needToWaitToProceed && !stores.user.data.isPremium, + () => stores.user.isLoggedIn && stores.features.features.needToWaitToProceed && !stores.user.data.isPremium, (isEnabled) => { if (isEnabled) { debug('Enabling `delayApp` feature'); diff --git a/src/features/shareFranz/Component.js b/src/features/shareFranz/Component.js new file mode 100644 index 000000000..753176e9c --- /dev/null +++ b/src/features/shareFranz/Component.js @@ -0,0 +1,160 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { observer } from 'mobx-react'; +import injectSheet from 'react-jss'; +import { defineMessages, intlShape } from 'react-intl'; +import { Button } from '@meetfranz/forms'; +import { H1, Icon } from '@meetfranz/ui'; + +import Modal from '../../components/ui/Modal'; +import { state } from '.'; +import { gaEvent } from '../../lib/analytics'; + +const messages = defineMessages({ + headline: { + id: 'feature.shareFranz.headline', + defaultMessage: '!!!Franz is better together!', + }, + text: { + id: 'feature.shareFranz.text', + defaultMessage: '!!!Tell your friends and colleagues how awesome Franz is and help us to spread the word.', + }, + actions: { + email: { + id: 'feature.shareFranz.action.email', + defaultMessage: '!!!Share as email', + }, + facebook: { + id: 'feature.shareFranz.action.facebook', + defaultMessage: '!!!Share on Facebook', + }, + twitter: { + id: 'feature.shareFranz.action.twitter', + defaultMessage: '!!!Share on Twitter', + }, + }, + shareText: { + email: { + id: 'feature.shareFranz.shareText.email', + defaultMessage: '!!! I\'ve added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com', + }, + twitter: { + id: 'feature.shareFranz.shareText.twitter', + defaultMessage: '!!! I\'ve added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @MeetFranz', + }, + }, +}); + +const styles = theme => ({ + modal: { + width: '80%', + maxWidth: 600, + background: theme.styleTypes.primary.accent, + textAlign: 'center', + color: theme.styleTypes.primary.contrast, + }, + heartContainer: { + display: 'flex', + justifyContent: 'center', + borderRadius: '100%', + background: theme.brandDanger, + padding: 20, + width: 100, + height: 100, + margin: [-70, 'auto', 30], + }, + heart: { + fill: theme.styleTypes.primary.contrast, + }, + headline: { + textAlign: 'center', + fontSize: 40, + marginBottom: 20, + }, + actions: { + display: 'flex', + justifyContent: 'space-between', + marginTop: 30, + }, + cta: { + background: theme.styleTypes.primary.contrast, + color: theme.styleTypes.primary.accent, + + '& svg': { + fill: theme.styleTypes.primary.accent, + }, + }, +}); + +export default @injectSheet(styles) @observer class ShareFranzModal extends Component { + static propTypes = { + classes: PropTypes.object.isRequired, + } + + static contextTypes = { + intl: intlShape, + }; + + close() { + state.isModalVisible = false; + } + + render() { + const { isModalVisible } = state; + + const { + classes, + } = this.props; + + const { intl } = this.context; + + return ( + +

+ +
+

+ {intl.formatMessage(messages.headline)} +

+

{intl.formatMessage(messages.text)}

+
+
+ + ); + } +} diff --git a/src/features/shareFranz/index.js b/src/features/shareFranz/index.js new file mode 100644 index 000000000..3a8ec95d3 --- /dev/null +++ b/src/features/shareFranz/index.js @@ -0,0 +1,52 @@ +import { observable, reaction } from 'mobx'; +import ms from 'ms'; + +import { state as delayAppState } from '../delayApp'; +import { gaEvent, gaPage } from '../../lib/analytics'; + +export { default as Component } from './Component'; + +const debug = require('debug')('Franz:feature:shareFranz'); + +const defaultState = { + isModalVisible: false, + lastShown: null, +}; + +export const state = observable(defaultState); + +export default function initialize(stores) { + debug('Initialize shareFranz feature'); + + window.franz.features.shareFranz = { + state, + }; + + function showModal() { + debug('Showing share window'); + + state.isModalVisible = true; + + gaEvent('Share Franz', 'show'); + gaPage('/share-modal'); + } + + reaction( + () => stores.user.isLoggedIn, + () => { + setTimeout(() => { + if (stores.settings.stats.appStarts % 30 === 0) { + if (delayAppState.isDelayAppScreenVisible) { + debug('Delaying share modal by 5 minutes'); + setTimeout(() => showModal(), ms('5m')); + } else { + showModal(); + } + } + }, ms('2s')); + }, + { + fireImmediately: true, + }, + ); +} -- cgit v1.2.3-54-g00ecf From 645850d341edb9b6a1e8e033dfb738717ad10a82 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Mon, 25 Feb 2019 16:47:32 +0100 Subject: Fix service count --- src/features/shareFranz/Component.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src/features') diff --git a/src/features/shareFranz/Component.js b/src/features/shareFranz/Component.js index 753176e9c..d463664df 100644 --- a/src/features/shareFranz/Component.js +++ b/src/features/shareFranz/Component.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { observer } from 'mobx-react'; +import { observer, inject } from 'mobx-react'; import injectSheet from 'react-jss'; import { defineMessages, intlShape } from 'react-intl'; import { Button } from '@meetfranz/forms'; @@ -9,6 +9,7 @@ import { H1, Icon } from '@meetfranz/ui'; import Modal from '../../components/ui/Modal'; import { state } from '.'; import { gaEvent } from '../../lib/analytics'; +import ServicesStore from '../../stores/ServicesStore'; const messages = defineMessages({ headline: { @@ -86,7 +87,7 @@ const styles = theme => ({ }, }); -export default @injectSheet(styles) @observer class ShareFranzModal extends Component { +export default @injectSheet(styles) @inject('stores') @observer class ShareFranzModal extends Component { static propTypes = { classes: PropTypes.object.isRequired, } @@ -104,8 +105,11 @@ export default @injectSheet(styles) @observer class ShareFranzModal extends Comp const { classes, + stores, } = this.props; + const serviceCount = stores.services.all.length; + const { intl } = this.context; return ( @@ -127,7 +131,7 @@ export default @injectSheet(styles) @observer class ShareFranzModal extends Comp label={intl.formatMessage(messages.actions.email)} className={classes.cta} icon="mdiEmail" - href={`mailto:?subject=Meet the cool app Franz&body=${intl.formatMessage(messages.shareText.email, { count: 10 })}}`} + href={`mailto:?subject=Meet the cool app Franz&body=${intl.formatMessage(messages.shareText.email, { count: serviceCount })}}`} target="_blank" onClick={() => { gaEvent('Share Franz', 'share', 'Share via email'); @@ -147,7 +151,7 @@ export default @injectSheet(styles) @observer class ShareFranzModal extends Comp label={intl.formatMessage(messages.actions.twitter)} className={classes.cta} icon="mdiTwitter" - href={`http://twitter.com/intent/tweet?status=${intl.formatMessage(messages.shareText.twitter, { count: 10 })}`} + href={`http://twitter.com/intent/tweet?status=${intl.formatMessage(messages.shareText.twitter, { count: serviceCount })}`} target="_blank" onClick={() => { gaEvent('Share Franz', 'share', 'Share via Twitter'); @@ -158,3 +162,9 @@ export default @injectSheet(styles) @observer class ShareFranzModal extends Comp ); } } + +ShareFranzModal.wrappedComponent.propTypes = { + stores: PropTypes.shape({ + services: PropTypes.instanceOf(ServicesStore).isRequired, + }).isRequired, +}; -- cgit v1.2.3-54-g00ecf