diff --git a/electron/package.json b/electron/package.json index 31f5372..05f8865 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "qortal-hub", - "version": "0.5.3", + "version": "0.5.4-pre", "description": "A desktop app that gives you access to the Qortal network", "author": { "name": "", @@ -57,4 +57,4 @@ "capacitor", "electron" ] -} \ No newline at end of file +} diff --git a/src/ExtStates/NotAuthenticated.tsx b/src/ExtStates/NotAuthenticated.tsx index 6d580fe..789f0fe 100644 --- a/src/ExtStates/NotAuthenticated.tsx +++ b/src/ExtStates/NotAuthenticated.tsx @@ -34,7 +34,7 @@ import LanguageSelector from '../components/Language/LanguageSelector'; import { MyContext } from '../App'; const manifestData = { - version: '0.5.3', + version: '0.5.4', }; export const HtmlTooltip = styled(({ className, ...props }: TooltipProps) => ( diff --git a/src/components/Theme/ThemeContext.tsx b/src/components/Theme/ThemeContext.tsx index 0f24b4a..72d4f3b 100644 --- a/src/components/Theme/ThemeContext.tsx +++ b/src/components/Theme/ThemeContext.tsx @@ -21,7 +21,7 @@ const defaultTheme = { }; const ThemeContext = createContext({ - themeMode: 'light', + themeMode: 'dark', toggleTheme: () => {}, userThemes: [defaultTheme], addUserTheme: (themes) => {}, @@ -30,7 +30,7 @@ const ThemeContext = createContext({ }); export const ThemeProvider = ({ children }) => { - const [themeMode, setThemeMode] = useState('light'); + const [themeMode, setThemeMode] = useState('dark'); const [userThemes, setUserThemes] = useState([defaultTheme]); const [currentThemeId, setCurrentThemeId] = useState('default'); diff --git a/src/components/UserLookup.tsx/UserLookup.tsx b/src/components/UserLookup.tsx/UserLookup.tsx index 0b19ba1..ee0b8c9 100644 --- a/src/components/UserLookup.tsx/UserLookup.tsx +++ b/src/components/UserLookup.tsx/UserLookup.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { DrawerUserLookup } from '../Drawer/DrawerUserLookup'; import { Avatar, @@ -17,6 +17,7 @@ import { Table, CircularProgress, useTheme, + Autocomplete, } from '@mui/material'; import { getAddressInfo, getNameOrAddress } from '../../background'; import { getBaseApiReact } from '../../App'; @@ -31,6 +32,7 @@ import { subscribeToEvent, unsubscribeFromEvent, } from '../../utils/events'; +import { useNameSearch } from '../../hooks/useNameSearch'; function formatAddress(str) { if (str.length <= 12) return str; @@ -44,6 +46,9 @@ function formatAddress(str) { export const UserLookup = ({ isOpenDrawerLookup, setIsOpenDrawerLookup }) => { const theme = useTheme(); const [nameOrAddress, setNameOrAddress] = useState(''); + const [inputValue, setInputValue] = useState(''); + const { results, isLoading } = useNameSearch(inputValue); + const options = useMemo(() => results?.map((item) => item.name), [results]); const [errorMessage, setErrorMessage] = useState(''); const [addressInfo, setAddressInfo] = useState(null); const [isLoadingUser, setIsLoadingUser] = useState(false); @@ -120,6 +125,7 @@ export const UserLookup = ({ isOpenDrawerLookup, setIsOpenDrawerLookup }) => { const onClose = () => { setIsOpenDrawerLookup(false); setNameOrAddress(''); + setInputValue(''); setErrorMessage(''); setPayments([]); setIsLoadingUser(false); @@ -146,31 +152,39 @@ export const UserLookup = ({ isOpenDrawerLookup, setIsOpenDrawerLookup }) => { gap: '5px', }} > - setNameOrAddress(e.target.value)} - size="small" - placeholder="Address or Name" - autoComplete="off" - onKeyDown={(e) => { - if (e.key === 'Enter' && nameOrAddress) { - lookupFunc(); + onChange={(event: any, newValue: string | null) => { + if (!newValue) { + setNameOrAddress(''); + return; } + setNameOrAddress(newValue); + lookupFunc(newValue); }} + inputValue={inputValue} + onInputChange={(event, newInputValue) => { + setInputValue(newInputValue); + }} + id="controllable-states-demo" + loading={isLoading} + options={options} + sx={{ width: 300 }} + renderInput={(params) => ( + { + if (e.key === 'Enter' && nameOrAddress) { + lookupFunc(inputValue); + } + }} + /> + )} /> - { - lookupFunc(); - }} - > - - + { + const [nameList, setNameList] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const checkIfNameExisits = useCallback( + async (name: string, listLimit: number) => { + try { + if (!name) { + setNameList([]); + return; + } + + const res = await fetch( + `${getBaseApiReact()}/names/search?query=${name}&prefix=true&limit=${listLimit}` + ); + const data = await res.json(); + setNameList( + data?.map((item: any) => { + return { + name: item.name, + address: item.owner, + }; + }) + ); + } catch (error) { + console.error(error); + } finally { + setIsLoading(false); + } + }, + [] + ); + // Debounce logic + useEffect(() => { + setIsLoading(true); + const handler = setTimeout(() => { + checkIfNameExisits(value, limit); + }, 500); + + // Cleanup timeout if searchValue changes before the timeout completes + return () => { + clearTimeout(handler); + }; + }, [value, limit, checkIfNameExisits]); + return { + isLoading, + results: nameList, + }; +}; diff --git a/src/styles/index.css b/src/styles/index.css index 02c897f..ce338ba 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -42,31 +42,6 @@ opacity: 0.6; } -::-webkit-scrollbar-track { - background-color: transparent; -} - -::-webkit-scrollbar-track:hover { - background-color: transparent; -} - -::-webkit-scrollbar { - width: 16px; - height: 10px; -} - -::-webkit-scrollbar-thumb { - background-color: #444444; - border-radius: 8px; - background-clip: content-box; - border: 4px solid transparent; - transition: 0.3s background-color; -} - -::-webkit-scrollbar-thumb:hover { - background-color: #363636; -} - @property --var1 { syntax: ''; inherits: true; @@ -78,7 +53,7 @@ } .scrollable-container:hover { - --var1: #444444; + --var1: var(--primary-main); } .scrollable-container::-webkit-scrollbar-thumb { diff --git a/src/styles/theme-dark.ts b/src/styles/theme-dark.ts index 8929561..142ee54 100644 --- a/src/styles/theme-dark.ts +++ b/src/styles/theme-dark.ts @@ -32,6 +32,7 @@ export const darkThemeOptions: ThemeOptions = { unread: 'rgb(66, 151, 226)', }, }, + components: { MuiCard: { styleOverrides: { @@ -48,19 +49,12 @@ export const darkThemeOptions: ThemeOptions = { }, }, MuiCssBaseline: { - styleOverrides: { + styleOverrides: (theme) => ({ ':root': { - '--color-instance': 'rgb(30, 30, 32)', - '--color-instance-popover-bg': 'rgb(34, 34, 34)', '--Mail-Background': 'rgb(43, 43, 43)', - '--new-message-text': 'rgb(0, 0, 0)', '--bg-primary': 'rgba(31, 32, 35, 1)', '--bg-2': 'rgb(39, 40, 44)', - '--bg-3': 'rgba(0, 0, 0, 0.1)', - '--unread': 'rgb(66, 151, 226)', - '--danger': 'rgb(177, 70, 70)', - '--apps-circle': 'rgb(31, 32, 35)', - '--green': 'rgb(94, 176, 73)', + '--primary-main': theme.palette.primary.main, }, '*, *::before, *::after': { boxSizing: 'border-box', @@ -74,9 +68,32 @@ export const darkThemeOptions: ThemeOptions = { margin: 0, wordBreak: 'break-word', backgroundColor: 'var(--bg-primary)', - color: 'var(--new-message-text)', }, - }, + '::-webkit-scrollbar-track': { + backgroundColor: 'transparent', + }, + + '::-webkit-scrollbar-track:hover': { + backgroundColor: 'transparent', + }, + + '::-webkit-scrollbar': { + width: '16px', + height: '10px', + }, + + '::-webkit-scrollbar-thumb': { + backgroundColor: theme.palette.primary.main, + borderRadius: '8px', + backgroundClip: 'content-box', + border: '4px solid transparent', + transition: '0.3s background-color', + }, + + '::-webkit-scrollbar-thumb:hover': { + backgroundColor: theme.palette.primary.light, + }, + }), }, MuiIcon: { defaultProps: { diff --git a/src/styles/theme-light.ts b/src/styles/theme-light.ts index 15b1f8b..26ca782 100644 --- a/src/styles/theme-light.ts +++ b/src/styles/theme-light.ts @@ -6,9 +6,9 @@ export const lightThemeOptions: ThemeOptions = { palette: { mode: 'light', primary: { - main: 'rgb(162, 162, 221)', // old light becomes main + main: 'rgb(162, 162, 221)', dark: 'rgb(113, 198, 212)', - light: 'rgba(244, 244, 251, 1)', // former main becomes light + light: 'rgb(180, 200, 235)', }, secondary: { main: 'rgba(194, 222, 236, 1)', @@ -49,36 +49,57 @@ export const lightThemeOptions: ThemeOptions = { }, }, MuiCssBaseline: { - styleOverrides: { + styleOverrides: (theme) => ({ ':root': { - '--color-instance': 'rgba(30, 30, 32, 1)', - '--color-instance-popover-bg': 'rgba(34, 34, 34, 1)', '--Mail-Background': 'rgba(49, 51, 56, 1)', - '--new-message-text': 'rgba(0, 0, 0, 1)', '--bg-primary': 'rgba(31, 32, 35, 1)', '--bg-2': 'rgba(39, 40, 44, 1)', - '--bg-3': 'rgba(0, 0, 0, 0.1)', - '--unread': 'rgba(66, 151, 226, 1)', - '--danger': 'rgba(177, 70, 70, 1)', - '--apps-circle': 'rgba(31, 32, 35, 1)', - '--green': 'rgba(94, 176, 73, 1)', + '--primary-main': theme.palette.primary.main, }, + '*, *::before, *::after': { boxSizing: 'border-box', }, + html: { padding: 0, margin: 0, }, + body: { padding: 0, margin: 0, wordBreak: 'break-word', backgroundColor: 'var(--bg-primary)', - color: 'var(--new-message-text)', }, - }, + + '::-webkit-scrollbar-track': { + backgroundColor: 'transparent', + }, + + '::-webkit-scrollbar-track:hover': { + backgroundColor: 'transparent', + }, + + '::-webkit-scrollbar': { + width: '16px', + height: '10px', + }, + + '::-webkit-scrollbar-thumb': { + backgroundColor: theme.palette.primary.main, + borderRadius: '8px', + backgroundClip: 'content-box', + border: '4px solid transparent', + transition: '0.3s background-color', + }, + + '::-webkit-scrollbar-thumb:hover': { + backgroundColor: theme.palette.primary.light, + }, + }), }, + MuiIcon: { defaultProps: { style: {