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

Improve phrase to be allowed only by logged in users in free countries #1635

Merged
merged 20 commits into from
May 6, 2024
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
4 changes: 3 additions & 1 deletion src/components/Account/Login/Login.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
disableTour,
setUnloggedUserLocation,
updateUnloggedUserLocation,
enableAllTours
enableAllTours,
updateNavigationSettings
} from '../../App/App.actions';
import { getVoiceURI } from '../../../i18n';
import { isCordova, isElectron } from '../../../cordova-util';
Expand Down Expand Up @@ -48,6 +49,7 @@ export function logout() {
console.error(err);
}
return async dispatch => {
dispatch(updateNavigationSettings({ improvePhraseActive: false }));
dispatch(setUnloggedUserLocation(null));
dispatch(updateUnloggedUserLocation());
dispatch(logoutSuccess());
Expand Down
2 changes: 2 additions & 0 deletions src/components/App/App.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Settings from '../Settings';
import WelcomeScreen from '../WelcomeScreen';
import Analytics from '../Analytics';
import './App.css';
import LoginRequiredModal from '../LoggedInFeature/LoginRequiredModal';

export class App extends Component {
static propTypes = {
Expand Down Expand Up @@ -90,6 +91,7 @@ export class App extends Component {
<Route component={NotFound} />
</Switch>
<PremiumRequiredModal />
<LoginRequiredModal />
</div>
);
}
Expand Down
62 changes: 62 additions & 0 deletions src/components/LoggedInFeature/LoginRequiredModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';
import { connect } from 'react-redux';
import { hideLoginRequired } from '../../providers/SubscriptionProvider/SubscriptionProvider.actions';
import { Dialog } from '@material-ui/core';
import { Link } from 'react-router-dom';

import Button from '@material-ui/core/Button';

import WarningIcon from '@material-ui/icons/Warning';
import DialogContent from '@material-ui/core/DialogContent';
import { Typography } from '@material-ui/core';

import messages from './LoginRequiredModal.messages';
import { FormattedMessage } from 'react-intl';

import style from './LoginRequiredModal.module.css';

function LoginRequiredModal({ hideLoginRequired, loginRequiredModalState }) {
const { open } = loginRequiredModalState;

return (
<Dialog
open={open}
onClose={hideLoginRequired}
maxWidth="md"
aria-labelledby="dialog"
>
<DialogContent className={style.content}>
<WarningIcon fontSize="large" color="action" />
<Typography variant="h3">
<FormattedMessage {...messages.featureBlockedTitle} />
</Typography>
<Typography className={style.dialogText} variant="h6">
<FormattedMessage {...messages.featureBlockedText} />
</Typography>
<Button
onClick={hideLoginRequired}
color="primary"
variant="contained"
size="large"
component={Link}
to="/login-signup"
>
<FormattedMessage {...messages.loginSignupNow} />
</Button>
</DialogContent>
</Dialog>
);
}

const mapStateToProps = ({ subscription: { loginRequiredModalState } }) => ({
loginRequiredModalState
});

const mapDispatchToProps = {
hideLoginRequired
};

export default connect(
mapStateToProps,
mapDispatchToProps
)(LoginRequiredModal);
19 changes: 19 additions & 0 deletions src/components/LoggedInFeature/LoginRequiredModal.messages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineMessages } from 'react-intl';

export default defineMessages({
featureBlockedTitle: {
id: 'cboard.components.LoginRequiredModal.featureBlockedTitle',
defaultMessage: 'Login or Sign Up to use this feature'
},
featureBlockedText: {
id: 'cboard.components.LoginRequiredModal.featureBlockedText',
// Refer to un-logged in users as "anonymous users".
// https://english.stackexchange.com/questions/251800/a-word-for-a-non-logged-in-user
defaultMessage:
'This feature is disabled for anonymous users. To continue using it please sign up or login'
},
loginSignupNow: {
id: 'cboard.components.LoginRequiredModal.loginSignupNow',
defaultMessage: 'Login or Sign Up now'
}
});
26 changes: 26 additions & 0 deletions src/components/LoggedInFeature/LoginRequiredModal.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.content {
display: flex;
flex-direction: column;
align-content: center;
justify-content: center;
align-items: center;
text-align: center;
margin: 2em 3em;
}

.dialogText {
padding-bottom: 1em;
}

@media (max-width: 480px), (max-height: 400px) {
.content {
margin: 2em 1em;
}

.content h3 {
font-size: 2em;
}
.content h6 {
font-size: 1.2em;
}
}
20 changes: 17 additions & 3 deletions src/components/PremiumFeature/PremiumFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import {
updateIsSubscribed,
updateSubscription,
updateIsOnTrialPeriod,
showPremiumRequired
showPremiumRequired,
showLoginRequired
} from '../../providers/SubscriptionProvider/SubscriptionProvider.actions';
import { isLogged } from '../App/App.selectors';

function isUpdateSubscriberStatusNeeded(lastUpdated) {
if (!lastUpdated) return true;
Expand All @@ -22,8 +24,11 @@ function PremiumFeature({
isOnTrialPeriod,
isSubscribed,
isInFreeCountry,
isLogged,
showPremiumRequired,
lastUpdated
showLoginRequired,
lastUpdated,
isLoginRequired = false
}) {
const captured = event => {
if (isUpdateSubscriberStatusNeeded(lastUpdated)) {
Expand All @@ -33,6 +38,13 @@ function PremiumFeature({
updateIsOnTrialPeriod();
}

if (isLoginRequired && !isLogged && isInFreeCountry) {
event.stopPropagation();
event.preventDefault();
showLoginRequired();
return;
}

if (isInFreeCountry || isSubscribed || isOnTrialPeriod) return;
event.stopPropagation();
event.preventDefault();
Expand All @@ -47,6 +59,7 @@ function PremiumFeature({
}

const mapStateToProps = state => ({
isLogged: isLogged(state),
isOnTrialPeriod: state.subscription.isOnTrialPeriod,
isSubscribed: state.subscription.isSubscribed,
isInFreeCountry: state.subscription.isInFreeCountry,
Expand All @@ -57,7 +70,8 @@ const mapDispatchToProps = {
showPremiumRequired,
updateIsSubscribed,
updateSubscription,
updateIsInFreeCountry
updateIsInFreeCountry,
showLoginRequired
};

export default connect(
Expand Down
2 changes: 1 addition & 1 deletion src/components/Settings/Navigation/Navigation.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ class Navigation extends React.Component {
}
/>
<ListItemSecondaryAction>
<PremiumFeature>
<PremiumFeature isLoginRequired={true}>
<Switch
checked={this.state.improvePhraseActive || false}
onChange={this.toggleImprovePhraseActive}
Expand Down
14 changes: 14 additions & 0 deletions src/providers/SubscriptionProvider/SubscriptionProvider.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
IN_GRACE_PERIOD,
EXPIRED,
PROCCESING,
SHOW_LOGIN_REQUIRED,
HIDE_LOGIN_REQUIRED,
UNVERIFIED
} from './SubscriptionProvider.constants';
import API from '../../api';
Expand Down Expand Up @@ -393,3 +395,15 @@ export function hidePremiumRequired() {
type: HIDE_PREMIUM_REQUIRED
};
}

export function showLoginRequired() {
return {
type: SHOW_LOGIN_REQUIRED
};
}

export function hideLoginRequired() {
return {
type: HIDE_LOGIN_REQUIRED
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export const SHOW_PREMIUM_REQUIRED =
'cboard/subscription/SHOW_PREMIUM_REQUIRED';
export const HIDE_PREMIUM_REQUIRED =
'cboard/subscription/HIDE_PREMIUM_REQUIRED';
export const SHOW_LOGIN_REQUIRED = 'cboard/subscription/SHOW_LOGIN_REQUIRED';
export const HIDE_LOGIN_REQUIRED = 'cboard/subscription/HIDE_LOGIN_REQUIRED';

export const NOT_SUBSCRIBED = 'not_subscribed';
export const PROCCESING = 'proccesing';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
UPDATE_SUBSCRIPTION_ERROR,
SHOW_PREMIUM_REQUIRED,
HIDE_PREMIUM_REQUIRED,
NOT_SUBSCRIBED
NOT_SUBSCRIBED,
SHOW_LOGIN_REQUIRED,
HIDE_LOGIN_REQUIRED
} from './SubscriptionProvider.constants';
import {
LOGOUT,
Expand All @@ -27,6 +29,9 @@ const initialState = {
open: false,
showTryPeriodFinishedMessages: false
},
loginRequiredModalState: {
open: false
},
ownedProduct: '',
products: [
{
Expand Down Expand Up @@ -96,6 +101,21 @@ function subscriptionProviderReducer(state = initialState, action) {
state.premiumRequiredModalState.showTryPeriodFinishedMessages
}
};

case SHOW_LOGIN_REQUIRED:
return {
...state,
loginRequiredModalState: {
open: true
}
};
case HIDE_LOGIN_REQUIRED:
return {
...state,
loginRequiredModalState: {
open: false
}
};
default:
return state;
}
Expand Down
3 changes: 3 additions & 0 deletions src/translations/src/cboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
"cboard.components.Login.password": "Password",
"cboard.components.Login.cancel": "Cancel",
"cboard.components.Login.forgotPassword": "Forgot password?",
"cboard.components.LoginRequiredModal.featureBlockedTitle": "Login or Sign Up to use this feature",
"cboard.components.LoginRequiredModal.featureBlockedText": "This feature is disabled for anonymous users. To continue using it please sign up or login",
"cboard.components.LoginRequiredModal.loginSignupNow": "Login or Sign Up now",
"cboard.components.SignUp.signUp": "Sign Up",
"cboard.components.SignUp.name": "Name",
"cboard.components.SignUp.email": "Email",
Expand Down