-
+
{title}
- {message}
+ {message}
+
+
+
+
`;
-const notifyMessage = function(type, icon, title, message, payload) {
-
+const notifyMessage = function(type, icon, title, message, payload, remember = '') {
// action buttons
const actions = [];
const dismiss_btn = {
@@ -153,13 +157,15 @@ const notifyMessage = function(type, icon, title, message, payload) {
actions.splice(0, actions.length);
}
- let final_message = this.$t(message ?? '');
+ let final_message = '
' + this.$t(message.toString() ?? '') + '';
if (Array.isArray(message)) {
- final_message = message.map(m => ` <${m.tag ?? 'span'} class="${m.class}">${m.text}${m.tag ?? 'span'}> `).join('');
+ final_message = message.map(
+ m => ` <${m.tag ?? 'span'} class="${m.class}">${m.text}${m.tag ?? 'span'}> `,
+ ).join('');
}
let timeout = 4000;
- if (type === 'error') {
+ if (type === 'error' || type === 'info') {
timeout = 0;
}
@@ -170,15 +176,32 @@ const notifyMessage = function(type, icon, title, message, payload) {
let random = Math.floor(Math.random() * 1000000);
+
+ function replaceAllOccurrences(html, replacements) {
+ let modifiedHtml = html;
+ for (let [key, value] of Object.entries(replacements)) {
+ const regex = new RegExp(key.replace(/[-\\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g');
+ modifiedHtml = modifiedHtml.replace(regex, value);
+ }
+ return modifiedHtml;
+ }
+
+ const replacements = {
+ '{svg}': icon,
+ '{type}': type,
+ '{title}': title,
+ '{random}': random,
+ '{remember}': remember,
+ '{message}': final_message,
+ '{remember-my-choice}': this.$t('notification.dont_show_message_again'),
+ };
+
+ const finalHtml = replaceAllOccurrences(html, replacements);
+
return Notify.create({
timeout,
position,
- message: html
- .replace('{svg}', icon)
- .replace('{type}', type)
- .replace('{title}', title)
- .replace('{random}', random)
- .replace('{message}', final_message),
+ message: finalHtml,
html: true,
classes: 'c-notify',
actions,
@@ -252,15 +275,55 @@ const notifyNeutralMessage = function(message) {
);
};
+const notifyRememberInfo = function(title, message, payload, key) {
+ const id = `c-notify__checkbox--${key}`;
+ const storageKey = 'c-notify--dismissed-messages';
+ const dismissed = JSON.parse(localStorage.getItem(storageKey)) ?? {};
+ if (dismissed[id]) {
+ return;
+ }
+ const notification = notifyMessage.bind(this)(
+ 'info',
+ infoIcon,
+ title,
+ message,
+ payload,
+ key,
+ );
+
+ const handler = (event) => {
+ // If the user click the checkbox, we set the flag in the local storage
+ if (event.target.id === id) {
+ const checkbox = document.getElementById(id);
+ if (checkbox.checked) {
+ dismissed[id] = true;
+ } else {
+ delete dismissed[id];
+ }
+ localStorage.setItem(storageKey, JSON.stringify(dismissed));
+ } else {
+ // catching Dismiss button click
+ if (event.target.parentNode.classList.contains('q-btn__content')) {
+ window.removeEventListener('click', handler);
+ }
+ }
+ };
+
+ window.addEventListener('click', handler);
+ return notification;
+};
+
+
+
export default boot(({ app, store }) => {
- app.config.globalProperties.$errorNotification = errorNotification.bind(store);
- app.config.globalProperties.$unexpectedErrorNotification = unexpectedErrorNotification.bind(store);
- app.config.globalProperties.$warningNotification = warningNotification.bind(store);
- app.config.globalProperties.$successNotification = successNotification.bind(store);
- store['$errorNotification'] = app.config.globalProperties.$errorNotification;
- store['$unexpectedErrorNotification'] = app.config.globalProperties.$unexpectedErrorNotification;
- store['$warningNotification'] = app.config.globalProperties.$warningNotification;
- store['$successNotification'] = app.config.globalProperties.$successNotification;
+ app.config.globalProperties.$errorNotification = errorNotification.bind(store);
+ app.config.globalProperties.$unexpectedErrorNotification = unexpectedErrorNotification.bind(store);
+ app.config.globalProperties.$warningNotification = warningNotification.bind(store);
+ app.config.globalProperties.$successNotification = successNotification.bind(store);
+ store['$errorNotification'] = app.config.globalProperties.$errorNotification;
+ store['$unexpectedErrorNotification'] = app.config.globalProperties.$unexpectedErrorNotification;
+ store['$warningNotification'] = app.config.globalProperties.$warningNotification;
+ store['$successNotification'] = app.config.globalProperties.$successNotification;
// new Message notifications handlers
app.config.globalProperties.$notifySuccessTransaction = notifySuccessTransaction.bind(store);
@@ -270,6 +333,7 @@ export default boot(({ app, store }) => {
app.config.globalProperties.$notifyFailureWithAction = notifyFailureWithAction.bind(store);
app.config.globalProperties.$notifyDisconnected = notifyDisconnected.bind(store);
app.config.globalProperties.$notifyNeutralMessage = notifyNeutralMessage.bind(store);
+ app.config.globalProperties.$notifyRememberInfo = notifyRememberInfo.bind(store);
store['$notifySuccessTransaction'] = app.config.globalProperties.$notifySuccessTransaction;
store['$notifySuccessMessage'] = app.config.globalProperties.$notifySuccessMessage;
store['$notifySuccessCopy'] = app.config.globalProperties.$notifySuccessCopy;
@@ -277,6 +341,7 @@ export default boot(({ app, store }) => {
store['$notifyFailureWithAction'] = app.config.globalProperties.$notifyFailureWithAction;
store['$notifyDisconnected'] = app.config.globalProperties.$notifyDisconnected;
store['$notifyNeutralMessage'] = app.config.globalProperties.$notifyNeutralMessage;
+ store['$notifyRememberInfo'] = app.config.globalProperties.$notifyRememberInfo;
// transaction notifications handlers
store['$t'] = app.config.globalProperties.$t;
diff --git a/src/css/components/_notification.scss b/src/css/components/_notification.scss
index 934b770ab..60f037a79 100644
--- a/src/css/components/_notification.scss
+++ b/src/css/components/_notification.scss
@@ -29,6 +29,8 @@
}
// container will say if this notification is success or error and set the color
&__container {
+ --c-notify__checkbox--display: none;
+ --c-notify__message--align: center;
&--success {
--notify-color: #{$notify-success};
--c-notify__title--display: flex;
@@ -40,15 +42,33 @@
--c-notify__title--display: flex;
--c-notify__message--padding: 0 2rem;
}
+ &--info {
+ --notify-color: #{$notify-info};
+ --c-notify__title--display: flex;
+ --c-notify__message--padding: 0 2rem;
+ --c-notify__checkbox--display: block;
+ --c-notify__message--align: left;
+ }
&--neutral {
--notify-color: #{$notify-neutral};
--c-notify__title--display: none;
--c-notify__message--padding: 1.2rem 2rem;
--c-notify__header--animation: consuming-bar 5s linear forwards;
}
- display: flex;
+ display: flex;
flex-direction: column;
}
+ &__checkbox-container {
+ display: var(--c-notify__checkbox--display);
+ margin: 2rem 0 0 2rem;
+ input {
+ margin-right: 0.5rem;
+ }
+ label {
+ color: var(--text-color, #000);
+ @include text--paragraph;
+ }
+ }
&__header {
height: 8px;
background-color: var(--notify-color);
@@ -70,14 +90,21 @@
color: var(--notify-color);
font-weight: 600;
}
+ &--neutral {
+ display: none;
+ }
}
&__message {
color: var(--text-color, #000);
padding: var(--c-notify__message--padding);
- text-align: center;
+ text-align: var(--c-notify__message--align, center);
span {
@include text--paragraph;
}
+ &--subtitle {
+ font-weight: bold;
+ margin-bottom: 1rem;
+ }
}
&__action-btn {
color: var(--text-color, #000);
diff --git a/src/css/quasar.variables.sass b/src/css/quasar.variables.sass
index 8e448ab3e..7deecbe1a 100644
--- a/src/css/quasar.variables.sass
+++ b/src/css/quasar.variables.sass
@@ -27,3 +27,4 @@ $available-color: #172c6c
$notify-success: #255B00
$notify-error: #880000
$notify-neutral: #4D4D4D
+$notify-info: #008888
diff --git a/src/i18n/en-us/index.js b/src/i18n/en-us/index.js
index 9357f8f86..5194cdc26 100644
--- a/src/i18n/en-us/index.js
+++ b/src/i18n/en-us/index.js
@@ -27,8 +27,7 @@ export default {
home: {
terms: 'Terms of Service',
privacy: 'Privacy Policy',
- developers_banner_title: 'Developers',
- developers_banner_text: 'Find out how to integrate Telos Cloud Wallet into your app here',
+ telos_cloud_discontinued: 'Telos Cloud Wallet will be discontinued. It is crucial for you to transfer your assets out of your Telos Cloud Wallet Accounts before December 15th.',
wallet_logo_alt: 'Telos Wallet logo',
view_any_account: 'View Any Account',
connect_with_wallet: 'Connect Your Wallet',
@@ -46,10 +45,12 @@ export default {
metamask: 'MetaMask',
install_safepal: 'Install SafePal',
safepal: 'SafePal',
+ brave: 'Brave Wallet',
walletconnect: 'WalletConnect',
connect_your_wallet: 'Connect Your Wallet',
wallet_introduction: 'What is a Web Wallet?',
multiple_providers_notification_message: 'Multiple providers detected. Disable all providers except MetaMask to continue.',
+ enable_brave_notification_message: 'Brave Browser detected. Please enable the wallet in the browser config, refresh the page and try again.',
no_provider_action_label: 'Install {provider}',
no_injected_provider_found: '{providerName}\'s provider was not found.',
sign_in_with: 'Sign in with',
@@ -285,6 +286,7 @@ export default {
neutral_message_wrapping: 'Wrapping
{quantity} {symbol}',
neutral_message_unwrapping: 'Unwrapping
{quantity} {symbol}',
neutral_message_withdrawing: 'Withdrawing
{quantity} {symbol}',
+ dont_show_message_again: 'Don\'t show me this message again',
},
resources: {
title: 'Network Resources',
@@ -575,7 +577,7 @@ export default {
error_no_default_authenticator: 'No default authenticator found',
error_settings_not_found: 'Settings not found',
error_staked_ratio: 'Error in getting staked ratio',
- indexer_bad_health_warning: 'The indexer is not healthy. You may encounter outdated data.',
+ indexer_bad_health_warning: 'Data is temporarily out of sync and may be outdated.',
},
account: {
error_login_native: 'An error has occurred trying to login to the native chain',
@@ -611,4 +613,9 @@ export default {
seconds: 'seconds',
},
},
+ temporal: {
+ telos_cloud_discontinued_title: 'Important',
+ telos_cloud_discontinued_message_title: 'Telos Cloud Wallet will be discontinued',
+ telos_cloud_discontinued_message_body: 'It is crucial for you to transfer your assets out of your Telos Cloud Wallet Accounts before December 31st.',
+ },
};
diff --git a/src/pages/evm/nfts/NftInventoryPage.vue b/src/pages/evm/nfts/NftInventoryPage.vue
index cc18128e5..2a0763204 100644
--- a/src/pages/evm/nfts/NftInventoryPage.vue
+++ b/src/pages/evm/nfts/NftInventoryPage.vue
@@ -20,14 +20,16 @@ import EVMChainSettings from 'src/antelope/chains/EVMChainSettings';
import TableControls from 'components/evm/TableControls.vue';
import { truncateAddress } from 'src/antelope/stores/utils/text-utils';
-
const nftStore = useNftsStore();
const chainStore = useChainStore();
const accountStore = useAccountStore();
const chainSettings = (chainStore.currentChain.settings as EVMChainSettings);
-// This warns the user (once per session) that the indexer is not healthy and can be outdated data
-chainSettings.checkAndWarnIndexerHealth();
+//TODO: remove timeout, see https://github.com/telosnetwork/telos-wallet/issues/697
+setTimeout(() => {
+ // This warns the user (once per session) that the indexer is not healthy and can be outdated data
+ chainSettings.checkAndWarnIndexerHealth();
+}, 1000);
const router = useRouter();
const route = useRoute();
diff --git a/src/pages/home/EVMLoginButtons.vue b/src/pages/home/EVMLoginButtons.vue
index 3e1a14736..76d628dd5 100644
--- a/src/pages/home/EVMLoginButtons.vue
+++ b/src/pages/home/EVMLoginButtons.vue
@@ -5,6 +5,7 @@ import { QSpinnerFacebook } from 'quasar';
import { OreIdAuth } from 'src/antelope/wallets';
import { Menu } from 'src/pages/home/MenuType';
import InlineSvg from 'vue-inline-svg';
+import { isTodayBeforeTelosCloudDown } from 'src/App.vue';
export default defineComponent({
name: 'EVMLoginButtons',
@@ -37,10 +38,16 @@ export default defineComponent({
return e && (isMobile.value ? e.isSafePal : e._isSafePal);
});
+ const supportsBrave = computed(() => {
+ const e = window.ethereum as unknown as { [key:string]: boolean };
+ return e && e.isBraveWallet;
+ });
+
const showMetamaskButton = computed(() => !isMobile.value || supportsMetamask.value);
const showSafePalButton = computed(() => !isMobile.value || supportsSafePal.value);
const injectedProviderDetected = computed(() => !!window.ethereum);
const showWalletConnectButton = computed(() => !isMobile.value || !injectedProviderDetected.value || (isMobile.value && isBraveBrowser.value)); // temp solution until Brave support is added https://github.com/telosnetwork/telos-wallet/issues/501
+ const showBraveButton = isBraveBrowser.value && !isMobile.value;
const unsupportedExtensions = computed(() => {
const e = window.ethereum as unknown as { [key:string]: boolean };
@@ -69,7 +76,10 @@ export default defineComponent({
const setMetamaskAuthenticator = async () => {
setAuthenticator('Metamask', CURRENT_CONTEXT);
};
- const setSafepalAuthenticator = async () => {
+ const setBraveAuthenticator = async () => {
+ setAuthenticator('Brave', CURRENT_CONTEXT);
+ };
+ const setSafePalAuthenticator = async () => {
setAuthenticator('SafePal', CURRENT_CONTEXT);
};
const setWalletConnectAuthenticator = async () => {
@@ -102,6 +112,11 @@ export default defineComponent({
ant.config.notifyFailureMessage(message);
};
+ const notifyEnableBrave = () => {
+ const message = globalProps.$t('home.enable_brave_notification_message');
+ ant.config.notifyFailureMessage(message);
+ };
+
const isLoading = (loginName: string) => useFeedbackStore().isLoading(loginName);
const isLoadingOreId = (provider: string) =>
selectedOAuthProvider.value === provider &&
@@ -115,21 +130,27 @@ export default defineComponent({
emit('update:modelValue', Menu.CLOUD);
};
+
return {
isLoading,
isLoadingOreId,
supportsMetamask,
+ supportsBrave,
supportsSafePal,
showMetamaskButton,
+ showBraveButton,
showSafePalButton,
showWalletConnectButton,
setOreIdAuthenticator,
setMetamaskAuthenticator,
- setSafepalAuthenticator,
+ setBraveAuthenticator,
+ setSafePalAuthenticator,
setWalletConnectAuthenticator,
notifyNoProvider,
+ notifyEnableBrave,
redirectToMetamaskDownload,
redirectToSafepalDownload,
+ isTodayBeforeTelosCloudDown,
// menu navigation
showMainMenu,
showTelosCloudMenu,
@@ -145,7 +166,7 @@ export default defineComponent({
-