diff --git a/src/App.tsx b/src/App.tsx index 734c6c5..4f18330 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,8 +5,6 @@ import { useAppDispatch } from './store/hooks/redux' import { setApps, setKeys, setPending, setPerms } from './store/reducers/content.slice' import AppRoutes from './routes/AppRoutes' import { fetchProfile, ndk } from './modules/nostr' -import { useModalSearchParams } from './hooks/useModalSearchParams' -import { MODAL_PARAMS_KEYS } from './types/modal' import { ModalInitial } from './components/Modal/ModalInitial/ModalInitial' import { ModalImportKeys } from './components/Modal/ModalImportKeys/ModalImportKeys' import { ModalSignUp } from './components/Modal/ModalSignUp/ModalSignUp' @@ -14,7 +12,6 @@ import { ModalLogin } from './components/Modal/ModalLogin/ModalLogin' function App() { const [render, setRender] = useState(0) - const { handleOpen } = useModalSearchParams() const dispatch = useAppDispatch() const [isConnected, setIsConnected] = useState(false) diff --git a/src/components/Modal/ModalAppDetails/ModalAppDetails.tsx b/src/components/Modal/ModalAppDetails/ModalAppDetails.tsx index 37f09cb..4d69582 100644 --- a/src/components/Modal/ModalAppDetails/ModalAppDetails.tsx +++ b/src/components/Modal/ModalAppDetails/ModalAppDetails.tsx @@ -3,7 +3,7 @@ import { Button } from '@/shared/Button/Button' import { Input } from '@/shared/Input/Input' import { Modal } from '@/shared/Modal/Modal' import { MODAL_PARAMS_KEYS } from '@/types/modal' -import { Autocomplete, CircularProgress, Stack, Typography } from '@mui/material' +import { Autocomplete, Stack, Typography } from '@mui/material' import { StyledInput } from './styled' import { FormEvent, useEffect, useState } from 'react' import { isEmptyString } from '@/utils/helpers/helpers' @@ -13,6 +13,7 @@ import { selectApps } from '@/store' import { dbi } from '@/modules/db' import { useEnqueueSnackbar } from '@/hooks/useEnqueueSnackbar' import { setApps } from '@/store/reducers/content.slice' +import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner' export const ModalAppDetails = () => { const { getModalOpened, createHandleCloseReplace } = useModalSearchParams() @@ -118,7 +119,7 @@ export const ModalAppDetails = () => { } } - const isFormValid = !isEmptyString(url) && !isEmptyString(name) && !isEmptyString(icon) + const isFormValid = !isEmptyString(url) && !isEmptyString(name) return ( @@ -165,7 +166,7 @@ export const ModalAppDetails = () => { /> diff --git a/src/components/Modal/ModalImportKeys/ModalImportKeys.tsx b/src/components/Modal/ModalImportKeys/ModalImportKeys.tsx index c9913e4..9595b87 100644 --- a/src/components/Modal/ModalImportKeys/ModalImportKeys.tsx +++ b/src/components/Modal/ModalImportKeys/ModalImportKeys.tsx @@ -5,7 +5,7 @@ import { Button } from '@/shared/Button/Button' import { Input } from '@/shared/Input/Input' import { Modal } from '@/shared/Modal/Modal' import { MODAL_PARAMS_KEYS } from '@/types/modal' -import { CircularProgress, Stack, Typography, useTheme } from '@mui/material' +import { Stack, Typography, useTheme } from '@mui/material' import { StyledAppLogo } from './styled' import { useNavigate } from 'react-router-dom' import { useForm } from 'react-hook-form' @@ -18,6 +18,7 @@ import { fetchNip05 } from '@/utils/helpers/helpers' import { DOMAIN } from '@/utils/consts' import { CheckmarkIcon } from '@/assets' import { getPublicKey, nip19 } from 'nostr-tools' +import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner' const FORM_DEFAULT_VALUES = { username: '', @@ -69,12 +70,13 @@ export const ModalImportKeys = () => { } try { const { type, data } = nip19.decode(debouncedNsec) - const ok = type === 'nsec'; + const ok = type === 'nsec' setIsBadNsec(!ok) if (ok) { const npub = nip19.npubEncode( // @ts-ignore - getPublicKey(data)) + getPublicKey(data) + ) setIsTakenByNsec(!!nameNpub && nameNpub === npub) } else { setIsTakenByNsec(false) @@ -84,7 +86,8 @@ export const ModalImportKeys = () => { setIsTakenByNsec(false) return } -}, [debouncedNsec]) + // eslint-disable-next-line + }, [debouncedNsec]) useEffect(() => { checkNsecUsername() @@ -106,8 +109,8 @@ export const ModalImportKeys = () => { if (isLoading) return undefined try { const { nsec, username } = values - if (!nsec || !username) throw new Error("Enter username and nsec") - if (nameNpub && !isTakenByNsec) throw new Error("Name taken") + if (!nsec || !username) throw new Error('Enter username and nsec') + if (nameNpub && !isTakenByNsec) throw new Error('Name taken') setIsLoading(true) const k: any = await swicCall('importKey', username, nsec) notify('Key imported!', 'success') @@ -186,16 +189,14 @@ export const ModalImportKeys = () => { helperTextProps={{ sx: { '&.helper_text': { - color: isBadNsec - ? theme.palette.error.main - : theme.palette.textSecondaryDecorate.main, + color: isBadNsec ? theme.palette.error.main : theme.palette.textSecondaryDecorate.main, }, }, }} /> diff --git a/src/components/Modal/ModalLogin/ModalLogin.tsx b/src/components/Modal/ModalLogin/ModalLogin.tsx index e800f6e..ad3d1ad 100644 --- a/src/components/Modal/ModalLogin/ModalLogin.tsx +++ b/src/components/Modal/ModalLogin/ModalLogin.tsx @@ -4,7 +4,7 @@ import { useModalSearchParams } from '@/hooks/useModalSearchParams' import { swicCall } from '@/modules/swic' import { Modal } from '@/shared/Modal/Modal' import { MODAL_PARAMS_KEYS } from '@/types/modal' -import { CircularProgress, Stack, Typography } from '@mui/material' +import { Stack, Typography } from '@mui/material' import { StyledAppLogo } from './styled' import { Input } from '@/shared/Input/Input' import { Button } from '@/shared/Button/Button' @@ -16,6 +16,7 @@ import { DOMAIN } from '@/utils/consts' import { fetchNip05, fetchNpubNames } from '@/utils/helpers/helpers' import { usePassword } from '@/hooks/usePassword' import { dbi } from '@/modules/db' +import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner' const FORM_DEFAULT_VALUES = { username: '', @@ -142,7 +143,7 @@ export const ModalLogin = () => { error={!!errors.password} /> diff --git a/src/components/Modal/ModalSettings/ModalSettings.tsx b/src/components/Modal/ModalSettings/ModalSettings.tsx index 89f2ab7..edb8f16 100644 --- a/src/components/Modal/ModalSettings/ModalSettings.tsx +++ b/src/components/Modal/ModalSettings/ModalSettings.tsx @@ -1,8 +1,7 @@ import { useModalSearchParams } from '@/hooks/useModalSearchParams' -import { Button } from '@/shared/Button/Button' import { Modal } from '@/shared/Modal/Modal' import { MODAL_PARAMS_KEYS } from '@/types/modal' -import { Box, CircularProgress, Stack, Typography } from '@mui/material' +import { Box, Stack, Typography } from '@mui/material' import { StyledButton, StyledSettingContainer, StyledSynchedText } from './styled' import { SectionTitle } from '@/shared/SectionTitle/SectionTitle' import { CheckmarkIcon } from '@/assets' @@ -17,6 +16,7 @@ import { usePassword } from '@/hooks/usePassword' import { useAppSelector } from '@/store/hooks/redux' import { selectKeys } from '@/store' import { isValidPassphase, isWeakPassphase } from '@/modules/keys' +import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner' type ModalSettingsProps = { isSynced: boolean @@ -116,15 +116,7 @@ export const ModalSettings: FC = ({ isSynced }) => { {...inputProps} onChange={handlePasswordChange} value={enteredPassword} - // helperText={isPasswordInvalid ? 'Invalid password' : ''} placeholder="Enter a password" - // helperTextProps={{ - // sx: { - // '&.helper_text': { - // color: 'red', - // }, - // }, - // }} disabled={!isChecked} /> {isPasswordInvalid ? ( @@ -150,10 +142,9 @@ export const ModalSettings: FC = ({ isSynced }) => { )} - Sync {isLoading && } + Sync {isLoading && } - {/* */} ) diff --git a/src/components/Modal/ModalSignUp/ModalSignUp.tsx b/src/components/Modal/ModalSignUp/ModalSignUp.tsx index 9031cc1..327ea06 100644 --- a/src/components/Modal/ModalSignUp/ModalSignUp.tsx +++ b/src/components/Modal/ModalSignUp/ModalSignUp.tsx @@ -2,7 +2,7 @@ import { useEnqueueSnackbar } from '@/hooks/useEnqueueSnackbar' import { useModalSearchParams } from '@/hooks/useModalSearchParams' import { Modal } from '@/shared/Modal/Modal' import { MODAL_PARAMS_KEYS } from '@/types/modal' -import { CircularProgress, Stack, Typography, useTheme } from '@mui/material' +import { Stack, Typography, useTheme } from '@mui/material' import React, { ChangeEvent, useEffect, useState } from 'react' import { StyledAppLogo } from './styled' import { Input } from '@/shared/Input/Input' @@ -12,6 +12,7 @@ import { swicCall } from '@/modules/swic' import { useNavigate } from 'react-router-dom' import { DOMAIN } from '@/utils/consts' import { fetchNip05 } from '@/utils/helpers/helpers' +import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner' export const ModalSignUp = () => { const { getModalOpened, createHandleCloseReplace } = useModalSearchParams() @@ -113,7 +114,7 @@ export const ModalSignUp = () => { }} /> diff --git a/src/layout/Header/Header.tsx b/src/layout/Header/Header.tsx index b7f537c..9fe72e7 100644 --- a/src/layout/Header/Header.tsx +++ b/src/layout/Header/Header.tsx @@ -23,7 +23,7 @@ export const Header = () => { } const isDarkMode = themeMode === 'dark' - const themeIcon = isDarkMode ? : + const themeIcon = isDarkMode ? : const handleChangeMode = () => { dispatch(setThemeMode({ mode: isDarkMode ? 'light' : 'dark' })) diff --git a/src/pages/CreatePage/Create.Page.tsx b/src/pages/CreatePage/Create.Page.tsx index e0f75db..de5a56f 100644 --- a/src/pages/CreatePage/Create.Page.tsx +++ b/src/pages/CreatePage/Create.Page.tsx @@ -9,6 +9,7 @@ import { useModalSearchParams } from '@/hooks/useModalSearchParams' import { MODAL_PARAMS_KEYS } from '@/types/modal' import { useState } from 'react' import { getReferrerAppUrl } from '@/utils/helpers/helpers' +import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner' const CreatePage = () => { const notify = useEnqueueSnackbar() @@ -17,6 +18,8 @@ const CreatePage = () => { const [searchParams] = useSearchParams() + const [isLoading, setIsLoading] = useState(false) + const name = searchParams.get('name') || '' const token = searchParams.get('token') || '' const appNpub = searchParams.get('appNpub') || '' @@ -31,12 +34,14 @@ const CreatePage = () => { const handleClickAddAccount = async () => { try { + setIsLoading(true) const key: any = await swicCall('generateKey', name) - const appUrl = getReferrerAppUrl(); + const appUrl = getReferrerAppUrl() console.log('Created', key.npub, 'app', appUrl) setCreated(true) + setIsLoading(false) handleOpen(MODAL_PARAMS_KEYS.CONFIRM_CONNECT, { search: { @@ -53,6 +58,7 @@ const CreatePage = () => { }) } catch (error: any) { notify(error.message || error.toString(), 'error') + setIsLoading(false) } } @@ -88,7 +94,9 @@ const CreatePage = () => { Chosen name: {nip05} - Create account + + Create account {isLoading && } + What you need to know: diff --git a/src/pages/KeyPage/hooks/useTriggerConfirmModal.ts b/src/pages/KeyPage/hooks/useTriggerConfirmModal.ts index a5f6fb9..38cf272 100644 --- a/src/pages/KeyPage/hooks/useTriggerConfirmModal.ts +++ b/src/pages/KeyPage/hooks/useTriggerConfirmModal.ts @@ -70,12 +70,19 @@ export const useTriggerConfirmModal = (npub: string, pending: DbPending[], perms search: { appNpub: req.appNpub, reqId: req.id, - popup: isPopup ? 'true' : '' + popup: isPopup ? 'true' : '', }, }) break } - }, [connectPendings, filteredPendingReqs.length, handleOpen, isConfirmEventModalOpened, isConfirmConnectModalOpened]) + }, [ + connectPendings, + filteredPendingReqs.length, + handleOpen, + isConfirmEventModalOpened, + isConfirmConnectModalOpened, + isPopup, + ]) const handleOpenConfirmEventModal = useCallback(() => { if (!filteredPendingReqs.length || connectPendings.length) return undefined @@ -91,12 +98,12 @@ export const useTriggerConfirmModal = (npub: string, pending: DbPending[], perms handleOpen(MODAL_PARAMS_KEYS.CONFIRM_EVENT, { search: { appNpub, - popup: isPopup ? 'true' : '' + popup: isPopup ? 'true' : '', }, }) break } - }, [connectPendings.length, filteredPendingReqs.length, handleOpen, prepareEventPendings]) + }, [connectPendings.length, filteredPendingReqs.length, handleOpen, prepareEventPendings, isPopup]) useEffect(() => { handleOpenConfirmEventModal() diff --git a/src/pages/KeyPage/styled.tsx b/src/pages/KeyPage/styled.tsx index 2314e14..0d2d241 100644 --- a/src/pages/KeyPage/styled.tsx +++ b/src/pages/KeyPage/styled.tsx @@ -48,6 +48,7 @@ export const StyledEmptyAppsBox = styled(Box)(({ theme }) => { placeItems: 'center', color: theme.palette.text.primary, opacity: '0.6', + maxHeight: '100%', }, } }) diff --git a/src/shared/Button/Button.tsx b/src/shared/Button/Button.tsx index 1d42691..683ecde 100644 --- a/src/shared/Button/Button.tsx +++ b/src/shared/Button/Button.tsx @@ -28,20 +28,20 @@ const StyledButton = styled( }, color: theme.palette.text.primary, '&.disabled': { - opacity: 0.5, + background: `${theme.palette.backgroundSecondary.default}50`, cursor: 'not-allowed', }, } } return { ...commonStyles, - '&.button:is(:hover, :active, &, .disabled)': { + '&.button:is(:hover, :active, &)': { background: theme.palette.primary.main, }, color: theme.palette.text.secondary, '&.disabled': { color: theme.palette.text.secondary, - opacity: 0.5, + background: `${theme.palette.primary.main}50`, cursor: 'not-allowed', }, } diff --git a/src/shared/LoadingSpinner/LoadingSpinner.tsx b/src/shared/LoadingSpinner/LoadingSpinner.tsx new file mode 100644 index 0000000..a04222a --- /dev/null +++ b/src/shared/LoadingSpinner/LoadingSpinner.tsx @@ -0,0 +1,17 @@ +import { CircularProgress, CircularProgressProps, styled } from '@mui/material' +import { FC } from 'react' + +type LoadingSpinnerProps = CircularProgressProps & { + mode?: 'default' | 'secondary' +} + +export const LoadingSpinner: FC = (props) => { + return +} + +export const StyledCircularProgress = styled((props: LoadingSpinnerProps) => ( + +))(({ theme, mode = 'default' }) => ({ + marginLeft: '0.5rem', + color: mode === 'default' ? theme.palette.text.secondary : theme.palette.text.primary, +})) diff --git a/src/utils/helpers/helpers.ts b/src/utils/helpers/helpers.ts index 7f77b53..5d67e9a 100644 --- a/src/utils/helpers/helpers.ts +++ b/src/utils/helpers/helpers.ts @@ -125,8 +125,7 @@ export const getReferrerAppUrl = () => { if (!window.document.referrer) return '' try { const u = new URL(window.document.referrer.toLocaleLowerCase()) - if (u.hostname != DOMAIN && !u.hostname.endsWith("."+DOMAIN)) - return u.origin + if (u.hostname !== DOMAIN && !u.hostname.endsWith('.' + DOMAIN)) return u.origin } catch {} return '' }