diff --git a/src/lib/components/_main_/header/Header.svelte b/src/lib/components/_main_/header/Header.svelte index 6f7e2c226..3974d9b44 100644 --- a/src/lib/components/_main_/header/Header.svelte +++ b/src/lib/components/_main_/header/Header.svelte @@ -35,6 +35,8 @@ COMPONENT JS - BASIC import { sessionStore } from '$lib/store/session'; import { platfrom_lang_ssr, viewport_change } from '$lib/utils/platform-functions'; import AuthWidget from '../auth/Auth_Widget.svelte'; + import { doc, updateDoc } from 'firebase/firestore'; + import { db_firestore } from '$lib/firebase/init'; // ~~~~~~~~~~~~~~~~~~~~~ // COMPONENT VARIABLES @@ -91,9 +93,12 @@ COMPONENT JS - BASIC // COMPONENT METHODS // ~~~~~~~~~~~~~~~~~~~~~ - let setOnce = false; - $: if ($userBetarenaSettings.user != undefined && !setOnce) { - setOnce = true + let setUserLang = false; + $: if ($userBetarenaSettings.user != undefined + && !setUserLang + && PROFILE_URL != $page.route.id + ) { + setUserLang = true let userlang = $userBetarenaSettings.user?.scores_user_data?.lang console.log("🔴🔴🔴🔴 HERE!!!") selectLanguage(userlang) @@ -127,7 +132,8 @@ COMPONENT JS - BASIC $: if (browser) { hideSEO = true; - if (!langSelected) { + if (!langSelected && $userBetarenaSettings.user == undefined) { + console.log("🔴🔴🔴🔴👀 HERE!!!") langSelected = true; userBetarenaSettings.setLang( server_side_language @@ -415,13 +421,44 @@ COMPONENT JS - BASIC } } + $: if ($userBetarenaSettings?.lang + && PROFILE_URL == $page.route.id) { + update_select_lang() + } + + /** + * @description updates user's platform language preferrences + * firebase services; + * @returns {Promise} + */ + async function update_select_lang(): Promise { + dlog('🔵 Updating platform lang...'); + const lang = $userBetarenaSettings?.lang; + // [ℹ] (update)from localStorage() + userBetarenaSettings.updateLang( + lang + ); + // [ℹ] (update)from Firebase - Firestore + const userRef = doc( + db_firestore, + 'betarena_users', + $userBetarenaSettings?.user + ?.firebase_user_data?.uid + ); + await updateDoc(userRef, { + lang: lang + }); + dlog('🟢 Language has been updated', true); + } + /** * @description logout user; and additional ui changes */ async function logout(): Promise { dropdown_user_auth = false; + await goto(`/${$userBetarenaSettings.lang == 'en' ? '' : $userBetarenaSettings.lang}`, { replaceState: true }) userBetarenaSettings.signOutUser(); - await goto('/', { replaceState: true }) + setUserLang = false } // NOTE: ? @@ -1150,22 +1187,22 @@ TODO:FIXME: not generating for each LANG -
logout()} - > -

- Logout -

-
+ > + Logout +

+ {/if} diff --git a/src/lib/components/page/profile/Modal-ConnectWallet.svelte b/src/lib/components/page/profile/Modal-ConnectWallet.svelte index 01731f0e8..9df8ba93c 100644 --- a/src/lib/components/page/profile/Modal-ConnectWallet.svelte +++ b/src/lib/components/page/profile/Modal-ConnectWallet.svelte @@ -8,6 +8,7 @@ COMPONENT JS (w/ TS) import wallet from './assets/wallet.svg'; import metamask_icon from './assets/metamask.svg'; + import { dlog, PR_P_STY, PR_P_TAG, PR_P_TOG } from '$lib/utils/debug'; // ~~~~~~~~~~~~~~~~~~~~~ // COMPONENT VARIABLES @@ -34,6 +35,13 @@ COMPONENT JS (w/ TS) * @returns {Promise} */ async function connect_wallet_action(): Promise { + // [ℹ] restrict only to MetaMask (original) + if (!providerDetect('isMetaMask')[0]) { + dlog("🔴 Moralis Auth not found!") + alert('Please install the MetaMask Wallet Extension!') + toggle_modal() + return + } const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); const account = accounts[0]; dispatch('connect_wallet_action', { @@ -41,6 +49,90 @@ COMPONENT JS (w/ TS) }); } + /** + * Validates what Web3 wallet extension + * is being used for the platform + * @param walletType + */ + function providerDetect( + walletType: + | 'isMetaMask' + | 'isCoinbaseWallet' + | 'isBraveWallet' + ): [boolean, any] { + // [ℹ] no ethereum wallet present + if (!window.ethereum) { + return [false, null]; + // throw new Error("No injected ethereum object."); + } + + // [ℹ] default provider (single) assign + let target_wallet = undefined; + + // [ℹ] multiple provider(s) check true + if ( + Array.isArray(window.ethereum.providers) + ) { + if (walletType == 'isMetaMask') { + target_wallet = + window.ethereum.providers.find( + (provider) => + provider[walletType] && + provider?.isBraveWallet == undefined + ); + } + // [ℹ] alternative + // else { + // target_wallet = window.ethereum.providers.find((provider) => provider[walletType]) + // } + dlog(`${PR_P_TAG} 🔵 More than 1 provider identified! ${window.ethereum.providers.length}`, PR_P_TOG, PR_P_STY) + dlog(`${PR_P_TAG} target_wallet ${target_wallet}`, PR_P_TOG, PR_P_STY) + dlog(`${PR_P_TAG} window.ethereum.providers ${window.ethereum.providers}`, PR_P_TOG, PR_P_STY) + } else { + if ( + walletType == 'isMetaMask' && + window.ethereum?.isBraveWallet == + undefined && + window.ethereum?.isMetaMask != + undefined && + window.ethereum?.isMetaMask + ) { + target_wallet = + window.ethereum[walletType]; + } + // [ℹ] alternative + // else { + // target_wallet = window.ethereum[walletType] + // } + dlog(`${PR_P_TAG} 🔵 1 provider identified! ${window.ethereum}`, PR_P_TOG, PR_P_STY) + dlog(`${PR_P_TAG} target_wallet ${target_wallet}`, PR_P_TOG, PR_P_STY) + dlog(`${PR_P_TAG} window.ethereum ${window.ethereum}`, PR_P_TOG, PR_P_STY) + } + + // [ℹ] TARGET (THIS) single provider check true + if (target_wallet != undefined) { + dlog(`${PR_P_TAG} 🟢 ${walletType} identified`, PR_P_TOG, PR_P_STY) + // DOC: https://stackoverflow.com/questions/69377437/metamask-conflicting-with-coinbase-wallet + // DOC: https://stackoverflow.com/questions/72613011/whenever-i-click-on-connect-metamask-button-why-it-connects-the-coinbase-wallet + // DOC: https://stackoverflow.com/questions/68023651/how-to-connect-to-either-metamask-or-coinbase-wallet + // DOC: https://github.com/MetaMask/metamask-extension/issues/13622 + // NOTE: conflicting use of CoinBaseWallet & MetaMask + // NOTE: setting MetaMask as main wallet + // NOTE: IMPORTANT causes issues with FireFox + // target_wallet.request({ method: 'eth_requestAccounts' }); + // NOTE: Not working + // window.ethereum.setSelectedProvider(target_wallet); + // window.ethereum.request({ + // method: 'wallet_requestPermissions', + // params: [{ eth_accounts: {}}] + // }); + return [true, target_wallet]; + } else { + dlog(`${PR_P_TAG} 🔴 no target wallet (${walletType}) identified`, PR_P_TOG, PR_P_STY) + return [false, null]; + } + } + // ~~~~~~~~~~~~~~~~~~~~~ // VIEWPORT CHANGES // ~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/lib/components/page/profile/Widget-AccountSettings.svelte b/src/lib/components/page/profile/Widget-AccountSettings.svelte index 4adb33c51..bc4eb3504 100644 --- a/src/lib/components/page/profile/Widget-AccountSettings.svelte +++ b/src/lib/components/page/profile/Widget-AccountSettings.svelte @@ -49,6 +49,7 @@ COMPONENT JS (w/ TS) let fileInputElem: HTMLInputElement; let usernameInput: string; let usernameErrorExist: boolean; + let usernameErrorMsg: string; let profile_picture_exists: boolean = false; let profile_wallet_connected: boolean = false; let processing: boolean = false; @@ -204,9 +205,10 @@ COMPONENT JS (w/ TS) // [ℹ] validation [1] const valid = await username_update_validation() if (!valid) { - alert('🔴 Username is invalid') + dlog('🔴 Username is invalid...', true); return; } + usernameErrorMsg = undefined; // [ℹ] (update)from localStorage() userBetarenaSettings.updateUsername( usernameInput @@ -224,6 +226,12 @@ COMPONENT JS (w/ TS) dlog('🟢 Username updated', true); } + /** + * @description a function to validate the user + * input; returns boolean true/false; assigns + * appropiate error message; + * @returns {Promise} boolean + */ async function username_update_validation(): Promise { dlog('🔵 Validating username...', true); let valid = true; @@ -233,16 +241,36 @@ COMPONENT JS (w/ TS) const querySnapshot = await getDocs(queryUsername); // can be access individually; // DOC: https://firebase.google.com/docs/firestore/query-data/queries dlog(querySnapshot, false); - if (querySnapshot.docs.length > 0) valid = false; - // [ℹ] validation [2] - length - if (usernameInput.length < 3) valid = false; - // [ℹ] validation [3] - only-numbers - if (/^\d+$/.test(usernameInput)) valid = false; - // [ℹ] validation [4] - has a space - if (/\s/g.test(usernameInput)) valid = false; - // [ℹ] validation [5] - has special char - let format = /[ `!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/; - if (format.test(usernameInput)) valid = false; + if (querySnapshot.docs.length > 0) { + valid = false + usernameErrorMsg = 'Username is already in use'; + } + // [ℹ] validation [2] - length (min) + if (usernameInput.length < 3) { + valid = false; + usernameErrorMsg = 'Username must be greater than 3 characters'; + } + // [ℹ] validation [3] - length (min) + if (usernameInput.length > 15) { + valid = false; + usernameErrorMsg = 'Username must be less than 15 characters'; + } + // [ℹ] validation [4] - only-numbers + if (/^\d+$/.test(usernameInput)) { + valid = false; + usernameErrorMsg = 'Username must not contain only numbers'; + }; + // [ℹ] validation [5] - has a space + if (/\s/g.test(usernameInput)) { + valid = false; + usernameErrorMsg = 'Username must not contain spaces' + } + // [ℹ] validation [6] - has special char + let format = /[ `!@#$%^&*()+\-=\[\]{};':"\\|,.<>\/?~]/; + if (format.test(usernameInput)) { + valid = false; + usernameErrorMsg = 'Username cant have spaces or special characters' + } // [ℹ] return; return valid; } @@ -602,7 +630,21 @@ COMPONENT HTML aria-placeholder="Username input here" aria-label="Username input" bind:value={usernameInput} + class:input-error={usernameErrorMsg != undefined} /> + + {#if usernameErrorMsg} +

+ {usernameErrorMsg} +

+ {/if}