Skip to content

Commit

Permalink
Merge branch 'cboard-org:master' into fix/improve-phrase-label
Browse files Browse the repository at this point in the history
  • Loading branch information
maxicapodacqua authored Dec 18, 2023
2 parents 3105558 + 0d3c5d5 commit 101e86a
Show file tree
Hide file tree
Showing 14 changed files with 328 additions and 59 deletions.
8 changes: 7 additions & 1 deletion src/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -518,11 +518,17 @@ class API {
}
const headers = {
Authorization: `Bearer ${authToken}`,
requestOrigin
requestOrigin,
newVersion: 'true'
};
const { data } = await this.axiosInstance.get(`/subscriber/${userId}`, {
headers
});

if (data && !data.success) {
throw data;
}

return data;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/Settings/Settings.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import FullScreenDialog from '../UI/FullScreenDialog';
import Paper from '@material-ui/core/Paper';
import UserIcon from '../UI/UserIcon';
import SettingsTour from './SettingsTour.component';
import { isCordova, isAndroid, isIOS } from '../../cordova-util';
import { isCordova, isAndroid } from '../../cordova-util';

import './Settings.css';
import { CircularProgress } from '@material-ui/core';
Expand Down Expand Up @@ -96,7 +96,7 @@ export class Settings extends PureComponent {
}
];

if (!isIOS() && !isInFreeCountry) {
if (!isInFreeCountry) {
const subscribeSection = {
icon: <MonetizationOnIcon />,
text: messages.subscribe,
Expand Down
13 changes: 10 additions & 3 deletions src/components/Settings/Subscribe/Subscribe.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import './Subscribe.css';

import SubscriptionInfo from './SubscriptionInfo';
import SubscriptionPlans from './SubscriptionPlans';
import { CircularProgress } from '@material-ui/core';

const propTypes = {
/**
Expand All @@ -29,7 +30,8 @@ const propTypes = {
onRefreshSubscription: PropTypes.func,
onSubscribeCancel: PropTypes.func.isRequired,
onCancelSubscription: PropTypes.func.isRequired,
cancelSubscriptionStatus: PropTypes.string.isRequired
cancelSubscriptionStatus: PropTypes.string.isRequired,
updatingStatus: PropTypes.bool.isRequired
};

const defaultProps = {
Expand All @@ -46,7 +48,8 @@ const Subscribe = ({
onSubscribeCancel,
onPaypalApprove,
onCancelSubscription,
cancelSubscriptionStatus
cancelSubscriptionStatus,
updatingStatus
}) => {
return (
<div className="Subscribe">
Expand All @@ -56,7 +59,11 @@ const Subscribe = ({
onClose={onClose}
// fullWidth
>
{!subscription.isSubscribed ? (
{updatingStatus ? (
<div className="Subscribe__Loading__Container">
<CircularProgress />
</div>
) : !subscription.isSubscribed ? (
<SubscriptionPlans
subscription={subscription}
onRefreshSubscription={onRefreshSubscription}
Expand Down
1 change: 1 addition & 0 deletions src/components/Settings/Subscribe/Subscribe.constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export const EMPTY_PRODUCT = 'empty_product';
export const ON_TRIAL_PERIOD = 'on_trial_period';
export const GOOGLE_PLAY_STORE_URL =
'https://play.google.com/store/account/subscriptions';
export const APP_STORE_URL = 'https://www.apple.com/app-store/';
106 changes: 79 additions & 27 deletions src/components/Settings/Subscribe/Subscribe.container.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getUser, isLogged } from '../../App/App.selectors';
import API from '../../../api';
import messages from './Subscribe.messages';

import { isAndroid } from '../../../cordova-util';
import { isAndroid, isIOS } from '../../../cordova-util';
import {
updateSubscriberId,
updateSubscription,
Expand All @@ -34,14 +34,17 @@ export class SubscribeContainer extends PureComponent {
};

state = {
cancelSubscriptionStatus: ''
cancelSubscriptionStatus: '',
updatingStatus: true
};

componentDidMount() {
async componentDidMount() {
const { updateIsSubscribed, updatePlans } = this.props;
const requestOrigin =
'Function: componentDidMount - Component: Subscribe Container';
updateIsSubscribed(requestOrigin);
this.setState({ updatingStatus: true });
await updateIsSubscribed(requestOrigin);
this.setState({ updatingStatus: false });
updatePlans();
}

Expand Down Expand Up @@ -195,7 +198,7 @@ export class SubscribeContainer extends PureComponent {

let localReceipts = '';
let offers, offer;
if (isAndroid()) {
if (isAndroid() || isIOS()) {
const storeProducts = await window.CdvPurchase.store.products;
const prod = storeProducts.find(p => {
return p.id === product.subscriptionId;
Expand All @@ -207,14 +210,22 @@ export class SubscribeContainer extends PureComponent {
try {
await window.CdvPurchase.store.update();
offers = prod.offers;
offer = offers.find(offer => offer.tags[0] === product.tag);
const findCallback = isAndroid()
? offer => offer.tags[0] === product.tag
: offer => offer.productId === product.subscriptionId;
offer = offers.find(findCallback);
} catch (err) {
console.error('Cannot subscribe product. Error: ', err.message);
this.handleError(err);
return;
}
}

const filterInAppPurchaseIOSTransactions = uniqueReceipt =>
uniqueReceipt.transactions.filter(
transaction => transaction.transactionId !== 'appstore.application'
);

try {
// update the api
const requestOrigin =
Expand All @@ -225,40 +236,80 @@ export class SubscribeContainer extends PureComponent {
// check if current subscriber already bought in this device
if (localReceipts.length) {
const lastReceipt = localReceipts.slice(-1)[0];
if (
lastReceipt &&
lastReceipt?.transactions[0]?.nativePurchase?.orderId !==
subscriber.transaction?.transactionId
) {
this.handleError({
code: '0001',
message: intl.formatMessage(messages.googleAccountAlreadyOwns)
});
return;
if (isAndroid()) {
if (
lastReceipt &&
lastReceipt?.transactions[0]?.nativePurchase?.orderId !==
subscriber.transaction?.transactionId
) {
this.handleError({
code: '0001',
message: intl.formatMessage(messages.googleAccountAlreadyOwns)
});
return;
}
}
if (isIOS()) {
//IOS have a unique receipt here => 'lastReceipt'
const inAppPurchaseTransactions = filterInAppPurchaseIOSTransactions(
localReceipts[0]
);

const lastTransaction = inAppPurchaseTransactions.slice(-1)[0];
if (
inAppPurchaseTransactions.length > 0 &&
lastTransaction?.transactionId !==
subscriber.transaction?.transactionId
) {
this.handleError({
code: '0001',
message: intl.formatMessage(messages.appleAccountAlreadyOwns)
});
return;
}
}
}

await API.updateSubscriber(apiProduct);

// proceed with the purchase
if (isAndroid()) {
if (isAndroid() || isIOS()) {
const order = await window.CdvPurchase.store.order(offer);
if (order && order.isError) throw order;
updateSubscription({
ownedProduct: {
...product,
platform: 'android-playstore'
platform: isAndroid() ? 'android-playstore' : 'app-store'
}
});
}
} catch (err) {
if (err.response?.data.error === 'subscriber not found') {
const isSubscriberNotFound =
(err.response?.data?.error || err.error) === 'subscriber not found';

if (isSubscriberNotFound) {
// check if current subscriber already bought in this device
if (localReceipts.length) {
this.handleError({
code: '0001',
message: intl.formatMessage(messages.googleAccountAlreadyOwns)
});
return;
if (isAndroid()) {
if (localReceipts.length) {
this.handleError({
code: '0001',
message: intl.formatMessage(messages.googleAccountAlreadyOwns)
});
return;
}
}
if (isIOS()) {
const localInAppPurchaseTransactions = filterInAppPurchaseIOSTransactions(
localReceipts[0]
);

if (localInAppPurchaseTransactions.length) {
this.handleError({
code: '0001',
message: intl.formatMessage(messages.appleAccountAlreadyOwns)
});
return;
}
}
try {
const newSubscriber = {
Expand All @@ -269,13 +320,13 @@ export class SubscribeContainer extends PureComponent {
};
const res = await API.createSubscriber(newSubscriber);
updateSubscriberId(res._id);
if (isAndroid()) {
if (isAndroid() || isIOS()) {
const order = await window.CdvPurchase.store.order(offer);
if (order && order.isError) throw order;
updateSubscription({
ownedProduct: {
...product,
platform: 'android-playstore'
platform: isAndroid() ? 'android-playstore' : 'app-store'
}
});
}
Expand Down Expand Up @@ -306,6 +357,7 @@ export class SubscribeContainer extends PureComponent {
onPaypalApprove={this.handlePaypalApprove}
onCancelSubscription={this.handleCancelSubscription}
cancelSubscriptionStatus={this.state.cancelSubscriptionStatus}
updatingStatus={this.state.updatingStatus}
/>
);
}
Expand Down
7 changes: 7 additions & 0 deletions src/components/Settings/Subscribe/Subscribe.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
.Subscribe__Loading__Container {
padding: 1em;
height: 92vh;
display: flex;
justify-content: center;
align-items: center;
}
.Subscribe__Alert {
margin: 8px 0;
}
Expand Down
10 changes: 10 additions & 0 deletions src/components/Settings/Subscribe/Subscribe.messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ export default defineMessages({
id: 'cboard.components.Settings.Subscribe.not_subscribed',
defaultMessage: 'You are not subscribed. '
},
unverified: {
id: 'cboard.components.Settings.Subscribe.unverified',
defaultMessage:
'An error occurred during validation of your purchase. Please refresh'
},
refresh: {
id: 'cboard.components.Settings.Subscribe.refresh',
defaultMessage: 'Refresh'
Expand Down Expand Up @@ -148,6 +153,11 @@ export default defineMessages({
defaultMessage:
'It looks like your Google account has already purchased a product. Try restarting the app.'
},
appleAccountAlreadyOwns: {
id: 'cboard.components.Settings.Subscribe.appleAccountAlreadyOwns',
defaultMessage:
'It looks like your Apple account has already purchased a product. Try restarting the app.'
},
fallback: {
id: 'cboard.components.Settings.Subscribe.fallback',
defaultMessage: 'Wait please...'
Expand Down
15 changes: 12 additions & 3 deletions src/components/Settings/Subscribe/SubscriptionInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import {

import RefreshIcon from '@material-ui/icons/Refresh';
import IconButton from '../../UI/IconButton';
import { isAndroid, isElectron } from '../../../cordova-util';
import { GOOGLE_PLAY_STORE_URL } from './Subscribe.constants';
import { isAndroid, isElectron, isIOS } from '../../../cordova-util';
import { APP_STORE_URL, GOOGLE_PLAY_STORE_URL } from './Subscribe.constants';

const propTypes = {
ownedProduct: PropTypes.object.isRequired,
Expand Down Expand Up @@ -131,13 +131,15 @@ const SubscriptionInfo = ({
</div>
<div className="Subscribe__Info__Button__Container">
<Button
variant={isAndroid() ? 'contained' : 'text'}
variant={isAndroid() || isIOS() ? 'contained' : 'text'}
fullWidth={false}
color="primary"
disabled={ownedProduct.platform === 'paypal' && status !== ACTIVE}
onClick={() => {
if (isAndroid() && ownedProduct.platform === 'android-playstore')
window.CdvPurchase.store.manageSubscriptions();
if (isIOS() && ownedProduct.platform === 'ios-appstore')
window.CdvPurchase.store.manageSubscriptions();
if (ownedProduct.platform === 'paypal') setCancelDialog(true);
if (!isAndroid() && ownedProduct.platform === 'android-playstore') {
if (isElectron()) {
Expand All @@ -148,6 +150,13 @@ const SubscriptionInfo = ({
window.open(GOOGLE_PLAY_STORE_URL, '_blank');
}
}
if (!isIOS() && ownedProduct.platform === 'ios-appstore') {
if (isElectron()) {
window.cordova.plugins.DefaultBrowser.open(APP_STORE_URL);
} else {
window.open(APP_STORE_URL, '_blank');
}
}
}}
style={{ marginLeft: '1em' }}
>
Expand Down
Loading

0 comments on commit 101e86a

Please sign in to comment.