+
{Object.keys(getAllowedLanguages()).map(lang =>
isCurrentLanguage(lang, current_language) ? (
diff --git a/packages/core/src/Stores/client-store.js b/packages/core/src/Stores/client-store.js
index 90df1147ec82..9aecc60bc185 100644
--- a/packages/core/src/Stores/client-store.js
+++ b/packages/core/src/Stores/client-store.js
@@ -695,7 +695,7 @@ export default class ClientStore extends BaseStore {
if (Object.keys(this.currencies_list).length > 0) {
const keys = Object.keys(this.currencies_list);
// Fix for edge case when logging out from crypto accounts causes Fiat list to be empty
- if (this.currencies_list[localize('Fiat')].length < 1) return 'USD';
+ if (this.currencies_list[localize('Fiat')]?.length < 1) return 'USD';
return Object.values(this.currencies_list[`${keys[0]}`])[0].text;
}
diff --git a/packages/core/src/Stores/common-store.js b/packages/core/src/Stores/common-store.js
index 00dc32ed2599..c0143e1137ea 100644
--- a/packages/core/src/Stores/common-store.js
+++ b/packages/core/src/Stores/common-store.js
@@ -13,77 +13,71 @@ export default class CommonStore extends BaseStore {
super({ root_store });
makeObservable(this, {
- server_time: observable,
- current_language: observable,
- is_language_changing: observable,
+ addRouteHistoryItem: action.bound,
allowed_languages: observable,
- has_error: observable,
+ app_id: observable,
+ app_router: observable,
+ app_routing_history: observable,
+ changeCurrentLanguage: action.bound,
+ changeSelectedLanguage: action.bound,
+ changing_language_timer_id: observable,
+ checkAppId: action.bound,
+ current_language: observable,
+ deposit_url: observable,
error: observable,
- network_status: observable,
+ has_error: observable,
+ init: action.bound,
+ is_from_derivgo: computed,
+ is_language_changing: observable,
is_network_online: observable,
is_socket_opened: observable,
- was_socket_opened: observable,
- services_error: observable,
- deposit_url: observable,
- withdraw_url: observable,
- app_routing_history: observable,
- app_router: observable,
- app_id: observable,
+ network_status: observable,
platform: observable,
+ routeBackInApp: action.bound,
+ routeTo: action.bound,
selected_contract_type: observable,
- changing_language_timer_id: observable,
- setSelectedContractType: action.bound,
- init: action.bound,
- checkAppId: action.bound,
- changeCurrentLanguage: action.bound,
+ server_time: observable,
+ services_error: observable,
+ setAppRouterHistory: action.bound,
setAppstorePlatform: action.bound,
- setPlatform: action.bound,
- is_from_derivgo: computed,
+ setDepositURL: action.bound,
+ setError: action.bound,
setInitialRouteHistoryItem: action.bound,
- setServerTime: action.bound,
setIsSocketOpened: action.bound,
setNetworkStatus: action.bound,
- setError: action.bound,
- showError: action.bound,
- setDepositURL: action.bound,
- setWithdrawURL: action.bound,
+ setPlatform: action.bound,
+ setSelectedContractType: action.bound,
+ setServerTime: action.bound,
setServicesError: action.bound,
- setAppRouterHistory: action.bound,
- routeTo: action.bound,
- addRouteHistoryItem: action.bound,
- changeSelectedLanguage: action.bound,
- routeBackInApp: action.bound,
+ setWithdrawURL: action.bound,
+ showError: action.bound,
+ was_socket_opened: observable,
+ withdraw_url: observable,
});
}
- server_time = ServerTime.get() || toMoment(); // fallback: get current time from moment.js
- current_language = currentLanguage;
- is_language_changing = false;
allowed_languages = Object.keys(getAllowedLanguages());
+ app_id = undefined;
+ app_router = { history: null };
+ app_routing_history = [];
+ changing_language_timer_id = '';
+ current_language = currentLanguage;
+ deposit_url = '';
has_error = false;
-
+ is_language_changing = false;
+ is_network_online = false;
+ is_socket_opened = false;
error = {
type: 'info',
message: '',
};
-
network_status = {};
- is_network_online = false;
- is_socket_opened = false;
- was_socket_opened = false;
-
- services_error = {};
-
- deposit_url = '';
- withdraw_url = '';
-
- app_routing_history = [];
- app_router = { history: null };
- app_id = undefined;
platform = '';
selected_contract_type = '';
-
- changing_language_timer_id = '';
+ server_time = ServerTime.get() || toMoment(); // fallback: get current time from moment.js
+ services_error = {};
+ was_socket_opened = false;
+ withdraw_url = '';
setSelectedContractType(contract_type) {
this.selected_contract_type = contract_type;
diff --git a/packages/core/src/Stores/ui-store.js b/packages/core/src/Stores/ui-store.js
index 930df2fa4106..37cf48411a20 100644
--- a/packages/core/src/Stores/ui-store.js
+++ b/packages/core/src/Stores/ui-store.js
@@ -26,6 +26,7 @@ export default class UIStore extends BaseStore {
is_dark_mode_on = window?.matchMedia?.('(prefers-color-scheme: dark)').matches && isMobile();
is_settings_modal_on = false;
is_language_settings_modal_on = false;
+ is_mobile_language_menu_open = false;
is_accounts_switcher_on = false;
account_switcher_disabled_message = '';
@@ -248,6 +249,7 @@ export default class UIStore extends BaseStore {
is_history_tab_active: observable,
is_landscape: observable,
is_language_settings_modal_on: observable,
+ is_mobile_language_menu_open: observable,
is_nativepicker_visible: observable,
is_positions_drawer_on: observable,
@@ -363,6 +365,7 @@ export default class UIStore extends BaseStore {
setShouldShowWarningModal: action.bound,
setSubSectionIndex: action.bound,
setTopUpInProgress: action.bound,
+ setMobileLanguageMenuOpen: action.bound,
toggleAccountsDialog: action.bound,
toggleAccountSettings: action.bound,
toggleAccountSignupModal: action.bound,
@@ -570,6 +573,10 @@ export default class UIStore extends BaseStore {
return this.is_dark_mode_on;
}
+ setMobileLanguageMenuOpen(is_mobile_language_menu_open) {
+ this.is_mobile_language_menu_open = is_mobile_language_menu_open;
+ }
+
toggleSetCurrencyModal() {
this.is_set_currency_modal_visible = !this.is_set_currency_modal_visible;
}
diff --git a/packages/core/src/sass/app/_common/components/settings-language.scss b/packages/core/src/sass/app/_common/components/settings-language.scss
index ebd6c519b3b2..d48a1e07d1c5 100644
--- a/packages/core/src/sass/app/_common/components/settings-language.scss
+++ b/packages/core/src/sass/app/_common/components/settings-language.scss
@@ -1,26 +1,28 @@
/** @define settings-language */
.settings-language {
+ margin-left: 1.6rem;
+ width: fit-content;
+
@include mobile {
display: flex;
- padding: 1.5rem 1.5rem 8rem;
+ flex-direction: column;
+ padding: 1.6rem 2.2rem 8rem;
+ width: 100%;
+ margin-left: 0;
}
&__language-container {
display: grid;
- grid-template-columns: repeat(4, minmax(90px, 1fr));
- grid-gap: 1.6rem;
- &--has-padding {
- padding: 1.6rem;
- }
+ grid-template-columns: repeat(4, min-content);
+ grid-gap: 0.8rem;
+ margin: 1.6rem 0;
+
@include mobile {
- grid-template-columns: repeat(2, minmax(50%, 1fr));
- grid-gap: 0.3rem;
+ grid-template-columns: repeat(2, minmax(40%, 1fr));
grid-template-rows: auto;
- width: 100%;
- &--has-padding {
- padding: 0 1.6rem;
- grid-gap: 0;
- }
+ grid-gap: initial;
+ margin: 0 auto;
+ padding: 0 0.8rem;
@include mobile {
&--disabled {
@@ -44,6 +46,9 @@
align-items: center;
border-radius: $BORDER_RADIUS;
padding: 16px;
+ width: 13.6rem;
+ height: 8.8rem;
+
@include mobile {
padding: 8px;
@@ -53,22 +58,26 @@
}
text-decoration: none;
background-color: var(--state-normal);
- cursor: pointer;
+
+ & * {
+ cursor: pointer;
+ }
&--active {
border: 1px solid var(--border-active);
color: var(--text-prominent);
+
+ & * {
+ cursor: not-allowed;
+ }
}
}
&-flag {
- width: 5rem;
- height: 4rem;
- cursor: pointer;
+ width: 3.6rem;
+ height: 2.8rem;
@include mobile {
margin-top: 1rem;
- width: 4rem;
- height: 5rem;
}
}
&-name {
@@ -93,8 +102,3 @@
}
}
}
-.account-form {
- &--language-settings {
- overflow: auto !important;
- }
-}
diff --git a/packages/shared/src/utils/files/file-uploader-utils.ts b/packages/shared/src/utils/files/file-uploader-utils.ts
index 552d71d4da88..8eac3f283cd9 100644
--- a/packages/shared/src/utils/files/file-uploader-utils.ts
+++ b/packages/shared/src/utils/files/file-uploader-utils.ts
@@ -80,7 +80,7 @@ export const readFiles = (files: TFile[], getFileReadErrorMessage: (t: string) =
documentFormat: getFormatFromMIME(f),
file_size: f.size,
...settings,
- documentType: settings?.documentType || 'utility_bill',
+ documentType: settings?.documentType ?? 'utility_bill',
};
resolve(file_obj);
};
diff --git a/packages/stores/src/mockStore.ts b/packages/stores/src/mockStore.ts
index db5b2fee963f..c3eb4c0d2416 100644
--- a/packages/stores/src/mockStore.ts
+++ b/packages/stores/src/mockStore.ts
@@ -305,6 +305,7 @@ const mock = (): TStores & { is_mock: boolean } => {
header_extension: null,
is_link_expired_modal_visible: false,
is_mobile: false,
+ is_mobile_language_menu_open: false,
is_positions_drawer_on: false,
is_reports_visible: false,
is_route_modal_on: false,
@@ -325,6 +326,7 @@ const mock = (): TStores & { is_mock: boolean } => {
openRealAccountSignup: jest.fn(),
setHasOnlyForwardingContracts: jest.fn(),
setIsClosingCreateRealAccountModal: jest.fn(),
+ setMobileLanguageMenuOpen: jest.fn(),
setRealAccountSignupEnd: jest.fn(),
setPurchaseState: jest.fn(),
shouldNavigateAfterChooseCrypto: jest.fn(),
diff --git a/packages/stores/types.ts b/packages/stores/types.ts
index 83e51c493146..13c55dcb4282 100644
--- a/packages/stores/types.ts
+++ b/packages/stores/types.ts
@@ -473,6 +473,7 @@ type TUiStore = {
is_app_disabled: boolean;
is_link_expired_modal_visible: boolean;
is_mobile: boolean;
+ is_mobile_language_menu_open: boolean;
is_positions_drawer_on: boolean;
is_services_error_visible: boolean;
is_unsupported_contract_modal_visible: boolean;
@@ -495,6 +496,7 @@ type TUiStore = {
setCurrentFocus: (value: string | null) => void;
setDarkMode: (is_dark_mode_on: boolean) => boolean;
setHasOnlyForwardingContracts: (has_only_forward_starting_contracts: boolean) => void;
+ setMobileLanguageMenuOpen: (is_mobile_language_menu_open: boolean) => void;
setReportsTabIndex: (value: number) => void;
setIsClosingCreateRealAccountModal: (value: boolean) => void;
setRealAccountSignupEnd: (status: boolean) => void;
diff --git a/packages/utils/src/__tests__/parse-url.spec.tsx b/packages/utils/src/__tests__/parse-url.spec.tsx
new file mode 100644
index 000000000000..a18d3bfcf313
--- /dev/null
+++ b/packages/utils/src/__tests__/parse-url.spec.tsx
@@ -0,0 +1,13 @@
+import { isExternalLink } from '../parse-url';
+
+describe('isExternalLink', () => {
+ it('should return true if the link matches the regex for external link', () => {
+ expect(isExternalLink('https://www.deriv.com')).toBeTruthy();
+ expect(isExternalLink('mailto://www.deriv.com')).toBeTruthy();
+ });
+
+ it("should return false if the link dosen't match the for external link", () => {
+ expect(isExternalLink('localhost.binary.sx')).toBeFalsy();
+ expect(isExternalLink('sftp://test_doc.com')).toBeFalsy();
+ });
+});
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index f16143b1e9c4..5c70d1ebd2a0 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -3,3 +3,4 @@ export { default as getActiveAuthTokenIDFromLocalStorage } from './getActiveAuth
export { default as getActiveLoginIDFromLocalStorage } from './getActiveLoginIDFromLocalStorage';
export { default as getTruncatedString } from './getTruncatedString';
export { default as unFormatLocaleString } from './unFormatLocaleString';
+export * from './parse-url';
diff --git a/packages/utils/src/parse-url.ts b/packages/utils/src/parse-url.ts
new file mode 100644
index 000000000000..cd1262aad5ac
--- /dev/null
+++ b/packages/utils/src/parse-url.ts
@@ -0,0 +1,6 @@
+/**
+ * Checks if the url passed via prop is the route to external URL resource by checking if it starts with http, https or mailto
+ * @param link string
+ * @returns boolean
+ */
+export const isExternalLink = (link: string) => /^(http|https|mailto):/i.test(link);