Skip to content

Commit

Permalink
feat(settings/general): revamp the language selection section
Browse files Browse the repository at this point in the history
  • Loading branch information
neuodev committed Aug 16, 2023
1 parent b4e7e0a commit 3da46dc
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// @flow
import { Component } from 'react';
import type { Node } from 'react';
import type { Node, ComponentType } from 'react';
import { observer } from 'mobx-react';
import classNames from 'classnames';
import Select from '../../../common/Select';
import { MenuItem, Typography } from '@mui/material';
import { intlShape } from 'react-intl';
import { Box, MenuItem, Typography } from '@mui/material';
import { defineMessages, intlShape } from 'react-intl';
import ReactToolboxMobxForm from '../../../../utils/ReactToolboxMobxForm';
import LocalizableError from '../../../../i18n/LocalizableError';
import styles from './GeneralSettings.scss';
Expand All @@ -14,84 +14,113 @@ import FlagLabel from '../../../widgets/FlagLabel';
import { tier1Languages } from '../../../../config/languagesConfig';
import globalMessages, { listOfTranslators } from '../../../../i18n/global-messages';
import type { $npm$ReactIntl$IntlFormat } from 'react-intl';
import { withLayout, InjectedLayoutProps } from '../../../../styles/context/layout';

type Props = {|
+languages: Array<LanguageType>,
+currentLocale: string,
+onSelectLanguage: {| locale: string |} => PossiblyAsync<void>,
+onSelectLanguage: ({| locale: string |}) => PossiblyAsync<void>,
+isSubmitting: boolean,
+error?: ?LocalizableError,
|};

const messages = defineMessages({
languageLabel: {
id: 'wallet.settings.general.language',
defaultMessage: '!!!Language',
},
languageSelectLabel: {
id: 'wallet.settings.general.revamp.languageSelectLabel',
defaultMessage: '!!!Select your language',
},
});

@observer
export default class GeneralSettings extends Component<Props> {
static defaultProps: {|error: void|} = {
error: undefined
class GeneralSettings extends Component<Props & InjectedLayoutProps> {
static defaultProps: {| error: void |} = {
error: undefined,
};

static contextTypes: {|intl: $npm$ReactIntl$IntlFormat|} = {
static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = {
intl: intlShape.isRequired,
};

selectLanguage: string => Promise<void> = async (locale) => {
selectLanguage: string => Promise<void> = async locale => {
await this.props.onSelectLanguage({ locale });
};

form: ReactToolboxMobxForm = new ReactToolboxMobxForm({
fields: {
languageId: {
label: this.context.intl.formatMessage(globalMessages.languageSelectLabel),
label: this.context.intl.formatMessage(
this.props.isRevampLayout
? messages.languageSelectLabel
: globalMessages.languageSelectLabel
),
value: this.props.currentLocale,
}
}
},
},
});

render(): Node {
const { languages, isSubmitting, error } = this.props;
const { languages, isSubmitting, error, isRevampLayout } = this.props;
const { intl } = this.context;
const { form } = this;
const languageId = form.$('languageId');
const languageOptions = languages.map(language => ({
value: language.value,
label: intl.formatMessage(language.label),
svg: language.svg
svg: language.svg,
}));
const componentClassNames = classNames([styles.component, 'general']);

return (
<div className={componentClassNames}>
<Select
labelId="languages-select"
{...languageId.bind()}
onChange={this.selectLanguage}
disabled={isSubmitting}
renderValue={value => (
<Typography variant="body2">
{languageOptions.filter(item => item.value === value)[0].label}
</Typography>
)}
{isRevampLayout && (
<Typography variant="body1" mb="16px" color="grayscale.900" fontWeight={500}>
{intl.formatMessage(messages.languageLabel)}
</Typography>
)}
<Box
sx={{
width: isRevampLayout ? '506px' : '100%',
}}
>
{languageOptions.map(option => (
<MenuItem key={option.value} value={option.value}>
<FlagLabel svg={option.svg} label={option.label} />
</MenuItem>
))}
</Select>
{error && <p className={styles.error}>{intl.formatMessage(error, error.values)}</p>}
<Select
labelId="languages-select"
{...languageId.bind()}
onChange={this.selectLanguage}
disabled={isSubmitting}
renderValue={value => (
<Typography variant="body2">
{languageOptions.filter(item => item.value === value)[0].label}
</Typography>
)}
>
{languageOptions.map(option => (
<MenuItem key={option.value} value={option.value}>
<FlagLabel svg={option.svg} label={option.label} />
</MenuItem>
))}
</Select>
{error && <p className={styles.error}>{intl.formatMessage(error, error.values)}</p>}
</Box>

{!tier1Languages.includes(languageId.value) &&
{!tier1Languages.includes(languageId.value) && (
<div className={styles.info}>
<h1>{intl.formatMessage(globalMessages.languageSelectLabelInfo)}</h1>
<p>
{intl.formatMessage(globalMessages.languageSelectInfo)}
{' '}
{listOfTranslators(intl.formatMessage(globalMessages.translationContributors),
intl.formatMessage(globalMessages.translationAcknowledgment))}
{intl.formatMessage(globalMessages.languageSelectInfo)}{' '}
{listOfTranslators(
intl.formatMessage(globalMessages.translationContributors),
intl.formatMessage(globalMessages.translationAcknowledgment)
)}
</p>
</div>
}

)}
</div>
);
}
}

export default (withLayout(GeneralSettings): ComponentType<Props>);
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import globalMessages from '../../../i18n/global-messages';
import type { $npm$ReactIntl$IntlFormat } from 'react-intl';
import SubMenu from '../../topbar/SubMenu';

const messages = defineMessages({
export const settingsMenuMessages = defineMessages({
general: {
id: 'settings.menu.general.link.label',
defaultMessage: '!!!General',
Expand Down Expand Up @@ -44,12 +44,12 @@ export default class SettingsMenu extends Component<Props> {

const settingOptions: Array<Object> = [
{
label: intl.formatMessage(messages.general),
label: intl.formatMessage(settingsMenuMessages.general),
route: ROUTES.SETTINGS.GENERAL,
className: 'general',
},
{
label: intl.formatMessage(messages.blockchain),
label: intl.formatMessage(settingsMenuMessages.blockchain),
route: ROUTES.SETTINGS.BLOCKCHAIN,
className: 'blockchain',
},
Expand All @@ -59,7 +59,7 @@ export default class SettingsMenu extends Component<Props> {
className: 'wallet',
},
!environmnent.isProduction() && {
label: intl.formatMessage(messages.externalStorage),
label: intl.formatMessage(settingsMenuMessages.externalStorage),
route: ROUTES.SETTINGS.EXTERNAL_STORAGE,
className: 'externalStorage',
},
Expand All @@ -74,7 +74,7 @@ export default class SettingsMenu extends Component<Props> {
className: 'support',
},
{
label: intl.formatMessage(messages.levelOfComplexity),
label: intl.formatMessage(settingsMenuMessages.levelOfComplexity),
route: ROUTES.SETTINGS.LEVEL_OF_COMPLEXITY,
className: 'levelOfComplexity',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Node } from 'react';
import { Component } from 'react';
import { observer } from 'mobx-react';
import { computed } from 'mobx';
import { defineMessages, intlShape } from 'react-intl';
import { defineMessages, intlShape } from 'react-intl';
import { handleExternalLinkClick } from '../../../utils/routing';
import GeneralSettings from '../../../components/settings/categories/general-setting/GeneralSettings';
import type { InjectedOrGenerated } from '../../../types/injectedPropsType';
Expand All @@ -15,11 +15,13 @@ import type { LanguageType } from '../../../i18n/translations';
import { THEMES } from '../../../styles/utils';
import type { Theme } from '../../../styles/utils';
import { PublicDeriver } from '../../../api/ada/lib/storage/models/PublicDeriver';
import { ReactComponent as AdaCurrency } from '../../../assets/images/currencies/ADA.inline.svg';
import { ReactComponent as AdaCurrency } from '../../../assets/images/currencies/ADA.inline.svg';
import { unitOfAccountDisabledValue } from '../../../types/unitOfAccountType';
import type { UnitOfAccountSettingType } from '../../../types/unitOfAccountType';
import type { $npm$ReactIntl$IntlFormat } from 'react-intl';
import { trackSetUnitOfAccount, trackSetLocale } from '../../../api/analytics';
import { Typography } from '@mui/material';
import { settingsMenuMessages } from '../../../components/settings/menu/SettingsMenu';

const currencyLabels = defineMessages({
USD: {
Expand Down Expand Up @@ -60,41 +62,41 @@ type GeneratedData = typeof GeneralSettingsPage.prototype.generated;

@observer
export default class GeneralSettingsPage extends Component<InjectedOrGenerated<GeneratedData>> {

static contextTypes: {|intl: $npm$ReactIntl$IntlFormat|} = {
static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = {
intl: intlShape.isRequired,
};

onSelectUnitOfAccount: string => Promise<void> = async (value) => {
const unitOfAccount = (value === 'ADA')
? unitOfAccountDisabledValue
: { enabled: true, currency: value };
onSelectUnitOfAccount: string => Promise<void> = async value => {
const unitOfAccount =
value === 'ADA' ? unitOfAccountDisabledValue : { enabled: true, currency: value };
await this.generated.actions.profile.updateUnitOfAccount.trigger(unitOfAccount);
trackSetUnitOfAccount(value);
};

onSelectLanguage: {| locale: string |} => PossiblyAsync<void> = ({ locale }) => {
onSelectLanguage: ({| locale: string |}) => PossiblyAsync<void> = ({ locale }) => {
this.generated.actions.profile.updateLocale.trigger({ locale });
trackSetLocale(locale);
};

render(): Node {
const { intl } = this.context;
const profileStore = this.generated.stores.profile;
const coinPriceStore = this.generated.stores.coinPriceStore;

const isSubmittingLocale = profileStore.setProfileLocaleRequest.isExecuting;
const isSubmittingUnitOfAccount = profileStore.setUnitOfAccountRequest.isExecuting
|| coinPriceStore.refreshCurrentUnit.isExecuting;
const isSubmittingUnitOfAccount =
profileStore.setUnitOfAccountRequest.isExecuting ||
coinPriceStore.refreshCurrentUnit.isExecuting;
const { currentTheme } = profileStore;

const currencies = profileStore.UNIT_OF_ACCOUNT_OPTIONS.map(c => {
const name = this.context.intl.formatMessage(currencyLabels[c.symbol]);
const name = intl.formatMessage(currencyLabels[c.symbol]);
return {
value: c.symbol,
label: `${c.symbol} - ${name}`,
name,
price: coinPriceStore.getCurrentPrice('ADA', c.symbol),
svg: c.svg
svg: c.svg,
};
});
currencies.unshift({
Expand All @@ -111,6 +113,11 @@ export default class GeneralSettingsPage extends Component<InjectedOrGenerated<G

return (
<>
{profileStore.isRevampTheme && (
<Typography variant="h5" fontWeight={500} mb="24px">
{intl.formatMessage(settingsMenuMessages.general)}
</Typography>
)}
<GeneralSettings
onSelectLanguage={this.onSelectLanguage}
isSubmitting={isSubmittingLocale}
Expand Down Expand Up @@ -141,13 +148,11 @@ export default class GeneralSettingsPage extends Component<InjectedOrGenerated<G
});
}
}
this.generated.actions.profile.updateTheme.trigger({ theme })
this.generated.actions.profile.updateTheme.trigger({ theme });
}}
onExternalLinkClick={handleExternalLinkClick}
/>
<AboutYoroiSettingsBlock
wallet={this.generated.stores.wallets.selected}
/>
<AboutYoroiSettingsBlock wallet={this.generated.stores.wallets.selected} />
</>
);
}
Expand All @@ -166,10 +171,8 @@ export default class GeneralSettingsPage extends Component<InjectedOrGenerated<G
|}) => Promise<void>,
|},
updateUnitOfAccount: {|
trigger: (
params: UnitOfAccountSettingType
) => Promise<void>
|}
trigger: (params: UnitOfAccountSettingType) => Promise<void>,
|},
|},
router: {|
goToRoute: {|
Expand All @@ -194,32 +197,30 @@ export default class GeneralSettingsPage extends Component<InjectedOrGenerated<G
LANGUAGE_OPTIONS: Array<LanguageType>,
currentLocale: string,
currentTheme: Theme,
isRevampTheme: boolean,
setProfileLocaleRequest: {|
error: ?LocalizableError,
isExecuting: boolean,
|},
UNIT_OF_ACCOUNT_OPTIONS: Array<{|
svg: string,
symbol: string
symbol: string,
|}>,
setUnitOfAccountRequest: {|
error: ?LocalizableError,
isExecuting: boolean
isExecuting: boolean,
|},
unitOfAccount: UnitOfAccountSettingType
unitOfAccount: UnitOfAccountSettingType,
|},
wallets: {|
selected: null | PublicDeriver<>,
publicDerivers: Array<PublicDeriver<>>,
getLastSelectedWallet: void => ?PublicDeriver<>,
|},
coinPriceStore: {|
getCurrentPrice: (
from: string,
to: string
) => ?string,
getCurrentPrice: (from: string, to: string) => ?string,
lastUpdateTimestamp: null | number,
refreshCurrentUnit: {| isExecuting: boolean |}
refreshCurrentUnit: {| isExecuting: boolean |},
|},
|},
|} {
Expand All @@ -244,6 +245,7 @@ export default class GeneralSettingsPage extends Component<InjectedOrGenerated<G
LANGUAGE_OPTIONS: profileStore.LANGUAGE_OPTIONS,
currentLocale: profileStore.currentLocale,
currentTheme: profileStore.currentTheme,
isRevampTheme: profileStore.isRevampTheme,
UNIT_OF_ACCOUNT_OPTIONS: profileStore.UNIT_OF_ACCOUNT_OPTIONS,
unitOfAccount: profileStore.unitOfAccount,
setUnitOfAccountRequest: {
Expand Down
4 changes: 3 additions & 1 deletion packages/yoroi-extension/app/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,8 @@
"wallet.settings.resync.label": "Resync wallet with the blockchain",
"wallet.settings.resync.warning": "This will also cause failed transactions to disappear as they are not stored on the blockchain.",
"wallet.settings.unchangedPassword": "Password unchanged since wallet creation",
"wallet.settings.general.language": "Language",
"wallet.settings.general.revamp.languageSelectLabel": "Select your language",
"wallet.staking.FAQPage": "FAQ page",
"wallet.staking.availableTotalRewards": "Available Total Rewards",
"wallet.staking.availableTotalRewardsHelper": "If the Reward amount is different than expected, see possible reasons of that on our {faqLink}.",
Expand Down Expand Up @@ -1057,4 +1059,4 @@
"yoroiTransfer.waiting.progressInfo.checkingAddresses": "Checking addresses funds",
"yoroiTransfer.waiting.progressInfo.restoringAddresses": "Fetching addresses",
"yoroiTransfer.waiting.title.label": "Wallet is being restored"
}
}

0 comments on commit 3da46dc

Please sign in to comment.