mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-05-15 22:26:58 +00:00
added autocomplete for user lookup. scrollbar theme
This commit is contained in:
parent
4d888e832f
commit
6b2d92d73d
@ -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": "",
|
||||
|
@ -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) => (
|
||||
|
@ -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');
|
||||
|
||||
|
@ -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',
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
autoFocus
|
||||
<Autocomplete
|
||||
value={nameOrAddress}
|
||||
onChange={(e) => 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) => (
|
||||
<TextField
|
||||
autoFocus
|
||||
autoComplete="off"
|
||||
{...params}
|
||||
label="Address or Name"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' && nameOrAddress) {
|
||||
lookupFunc(inputValue);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
lookupFunc();
|
||||
}}
|
||||
>
|
||||
<SearchIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
marginRight: '20px',
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
|
||||
<ButtonBase
|
||||
sx={{
|
||||
marginLeft: 'auto',
|
||||
|
55
src/hooks/useNameSearch.tsx
Normal file
55
src/hooks/useNameSearch.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { getBaseApiReact } from '../App';
|
||||
|
||||
interface NameListItem {
|
||||
name: string;
|
||||
address: string;
|
||||
}
|
||||
export const useNameSearch = (value: string, limit = 20) => {
|
||||
const [nameList, setNameList] = useState<NameListItem[]>([]);
|
||||
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,
|
||||
};
|
||||
};
|
@ -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: '<color>';
|
||||
inherits: true;
|
||||
@ -78,7 +53,7 @@
|
||||
}
|
||||
|
||||
.scrollable-container:hover {
|
||||
--var1: #444444;
|
||||
--var1: var(--primary-main);
|
||||
}
|
||||
|
||||
.scrollable-container::-webkit-scrollbar-thumb {
|
||||
|
@ -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: {
|
||||
|
@ -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: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user