Skip to content

Commit

Permalink
Merge branch 'master' into feature/ElectronAnalytics
Browse files Browse the repository at this point in the history
  • Loading branch information
martinbedouret committed Dec 18, 2023
2 parents b372a3c + 0d3c5d5 commit 6c8536c
Show file tree
Hide file tree
Showing 17 changed files with 349 additions and 60 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
14 changes: 13 additions & 1 deletion src/components/Board/Board.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -758,8 +758,20 @@ export function updateApiObjects(
.then(res => {
const updatedChildBoardId = res.id;
//create - update parent board
const updateTilesParentBoard = () =>
parentBoard.tiles.map(tile => {
if (tile.loadBoard === childBoard.id)
return { ...tile, loadBoard: updatedChildBoardId };
return tile;
});
const updatedParentBoard = {
...parentBoard,
tiles: createParentBoard
? updateTilesParentBoard()
: parentBoard.tiles
};
const action = createParentBoard ? createApiBoard : updateApiBoard;
return dispatch(action(parentBoard, parentBoard.id))
return dispatch(action(updatedParentBoard, parentBoard.id))
.then(res => {
const updatedParentBoardId = res.id;
//add new boards to the active communicator
Expand Down
6 changes: 5 additions & 1 deletion src/components/Board/Board.container.js
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ export class BoardContainer extends Component {

// Loggedin user?
if ('name' in userData && 'email' in userData) {
await this.handleApiUpdates(tile);
await this.handleApiUpdates(tile); // this function could mutate tthe tile
return;
}

Expand Down Expand Up @@ -1125,6 +1125,7 @@ export class BoardContainer extends Component {
//update the parent
updateBoard(parentBoardData);
}
// Untill here all is with shorts ids
//api updates
if (tile && tile.type === 'board') {
//child becomes parent
Expand Down Expand Up @@ -1166,6 +1167,9 @@ export class BoardContainer extends Component {
)
.then(parentBoardId => {
if (createParentBoard) {
/* Here the parentBoardData is not updated with the values
that updatedApiObjects store on the API. Inside the boards are already updated
an the value is not replaced because the oldboard Id was replaced on the updateApiObjects inside createApiBoardSuccess */
replaceBoard(
{ ...parentBoardData },
{ ...parentBoardData, id: parentBoardId }
Expand Down
4 changes: 4 additions & 0 deletions src/components/Board/Board.reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ function tileReducer(board, action) {
return {
...board,
tiles: [...board.tiles, { ...action.tile }]
/* some times when a tile folder is created here the last tile change loadBoard to a long Id with no reason
action tile before this copy has a short ID*/
};
case DELETE_TILES:
return {
Expand Down Expand Up @@ -165,6 +167,8 @@ function boardReducer(state = initialState, action) {

if (prev.id !== current.id) {
const boardIndex = boards.findIndex(b => b.id === prev.id);
/* On create a parent board the prev board doesn't exist with a short Id
because is already replaced by a long one */
if (boardIndex >= 0) {
boards[boardIndex] = current;
}
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
Loading

0 comments on commit 6c8536c

Please sign in to comment.