(feat:keydown): listen cross platform events

This commit is contained in:
ManishMadan2882
2024-11-20 17:04:45 +05:30
parent e0a3b8004c
commit 48f47351ee
3 changed files with 68 additions and 6 deletions

View File

@@ -32,6 +32,7 @@
"scripts": {
"build": "parcel build src/main.tsx --public-url ./",
"build:react": "parcel build src/index.ts",
"serve": "parcel serve -p 3000",
"dev": "parcel -p 3000",
"test": "jest",
"lint": "eslint",

View File

@@ -6,10 +6,10 @@ import { getSearchResults } from '../requests/searchAPI'
import { Result } from '@/types';
import MarkdownIt from 'markdown-it';
import DOMPurify from 'dompurify';
import { getOS } from '../utils/helper'
const themes = {
dark: {
bg: '#222327',
bg: '#000',
text: '#fff',
primary: {
text: "#FAFAFA",
@@ -47,6 +47,9 @@ const TextField = styled.input<{ inputWidth: string }>`
outline: none;
border: none;
background-color: ${props => props.theme.secondary.bg};
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
transition: background-color 128ms linear;
&:focus {
outline: none;
@@ -114,6 +117,7 @@ const ResultWrapper = styled.div`
const Markdown = styled.div`
line-height:20px;
font-size: 12px;
word-break: break-all;
pre {
padding: 8px;
width: 90%;
@@ -197,12 +201,25 @@ const NoResults = styled.div`
font-size: 1rem;
color: #888;
`;
const InfoButton = styled.button`
padding: 10px 4px 10px 4px;
display: block;
width: 100%;
color: inherit;
border-radius: 6px;
background-color: ${(props) => props.theme.bg};
text-align: center;
font-size: 14px;
margin-bottom: 8px;
border:1px solid ${(props) => props.theme.secondary.text};
`
export const SearchBar = ({
apiKey = "74039c6d-bff7-44ce-ae55-2973cbf13837",
apiHost = "https://gptcloud.arc53.com",
theme = "dark",
placeholder = "Search or Ask AI...",
width = "240px"
width = "256px"
}: SearchBarProps) => {
const [input, setInput] = React.useState<string>("");
const [loading, setLoading] = React.useState<boolean>(false);
@@ -213,6 +230,14 @@ export const SearchBar = ({
const [results, setResults] = React.useState<Result[]>([]);
const debounceTimeout = React.useRef<number | null>(null);
const abortControllerRef = React.useRef<AbortController | null>(null)
const browserOS = getOS();
const getKeyboardInstruction = () => {
if (browserOS === 'linux' || browserOS === 'win')
return "Ctrl K"
else if (browserOS === 'mac')
return "⌘ K"
else return "Enter"
}
React.useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
@@ -258,7 +283,11 @@ export const SearchBar = ({
}, [input])
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.ctrlKey && event.key === 'k') {
if (
((browserOS === 'win' || browserOS === 'linux') && event.ctrlKey && event.key === 'k') ||
(browserOS === 'mac' && event.metaKey && event.key === 'k') ||
((browserOS === 'android' || browserOS === 'ios' || browserOS === 'other') && event.key === 'Enter')
) {
event.preventDefault();
setIsWidgetOpen(true);
}
@@ -272,10 +301,12 @@ export const SearchBar = ({
<Main>
<Container>
<TextField
type='search'
spellCheck={false}
inputWidth={width}
onFocus={() => setIsResultVisible(true)}
ref={inputRef}
onSubmit={() => setIsWidgetOpen(true)}
onKeyDown={(e) => handleKeyDown(e)}
placeholder={placeholder}
value={input}
@@ -284,6 +315,7 @@ export const SearchBar = ({
{
input.length > 0 && isResultVisible && (
<SearchResults ref={resultsRef}>
<InfoButton>{`Press ${getKeyboardInstruction()} to Ask the AI`}</InfoButton>
{!loading ?
(results.length > 0 ?
results.map((res) => {
@@ -298,7 +330,7 @@ export const SearchBar = ({
<Title>{res.title}</Title>
<Content>
<Markdown
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(md.render((res.text + "...").substring(0, 256) + "...")) }}
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(md.render((res.text).substring(0, 256) + "...")) }}
/>
</Content>
</ResultWrapper>
@@ -313,7 +345,9 @@ export const SearchBar = ({
</SearchResults>
)
}
<Toolkit title='Press Ctrl + K to Ask AI'>Ctrl K</Toolkit>
<Toolkit title={`Press ${getKeyboardInstruction()} to Ask the AI`}>
{getKeyboardInstruction()}
</Toolkit>
</Container>
<WidgetCore
theme={theme}

View File

@@ -0,0 +1,27 @@
export const getOS = () => {
const platform = window.navigator.platform;
const userAgent = window.navigator.userAgent || window.navigator.vendor;
if (/Mac/i.test(platform)) {
return 'mac';
}
if (/Win/i.test(platform)) {
return 'win';
}
if (/Linux/i.test(platform) && !/Android/i.test(userAgent)) {
return 'linux';
}
if (/Android/i.test(userAgent)) {
return 'android';
}
if (/iPhone|iPad|iPod/i.test(userAgent)) {
return 'ios';
}
return 'other';
};