Skip to content

Commit

Permalink
✨ feat: 添加搜索区键盘操作支持
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Feb 14, 2021
1 parent 3df50b4 commit fe4cfec
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Checkbox, Space } from 'antd';
import cls from 'classnames';

import { SearchService } from '../../../useSearchService';
import { KeyboardService } from '../../useKeyboardService';
import { KeyboardService } from '../../../useKeyboardService';

import styles from './style.less';

Expand Down
13 changes: 6 additions & 7 deletions src/contentScripts/searchBar/app/SearchInput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import type { FC } from 'react';
import React, { useContext } from 'react';
import { Input } from 'antd';
import { KeyboardService, useKeyboardService } from './useKeyboardService';

import Options from './components/Options';

import { KeyboardService } from '../useKeyboardService';
import { SearchService } from '../useSearchService';

import styles from './style.less';

const SearchInput: FC = () => {
const { onSearchEvent } = useContext(SearchService);

const keyboardService = useKeyboardService();
const { inputRef, focusOnInput } = keyboardService;
const { inputRef, focusOnInput } = useContext(KeyboardService);

return (
<KeyboardService.Provider value={keyboardService}>
<>
<Input
autoFocus
ref={inputRef}
Expand All @@ -23,10 +23,9 @@ const SearchInput: FC = () => {
size={'large'}
onChange={onSearchEvent}
onFocus={focusOnInput}
// onKeyDown={onKeyDown}
/>
<Options />
</KeyboardService.Provider>
</>
);
};

Expand Down
16 changes: 14 additions & 2 deletions src/contentScripts/searchBar/app/SearchResult/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import React, { useContext } from 'react';
import type { FC } from 'react';
import { Skeleton } from 'antd';
import cls from 'classnames';

import { SearchService } from '../useSearchService';
import { KeyboardService } from '../useKeyboardService';
import RepoIcon from './RepoIcon';

import styles from './style.less';

const SearchResult: FC = () => {
const { result, loading } = useContext(SearchService);
const { selectResultIndex, handleResultIndex, focusKey } = useContext(
KeyboardService,
);

return (
<Skeleton
Expand All @@ -20,16 +25,23 @@ const SearchResult: FC = () => {
active
className={styles.skeleton}
>
{result?.map((item) => {
{result?.map((item, index) => {
const { title, info, id, url, target, type } = item;

return (
<div
key={id}
className={styles.row}
className={cls({
[styles.row]: true,
[styles.selected]:
focusKey === 'result' && selectResultIndex === index,
})}
onClick={() => {
window.open(url);
}}
onMouseEnter={() => {
handleResultIndex(index);
}}
>
<div className={styles.repo}>
{type === 'repo' ? (
Expand Down
5 changes: 4 additions & 1 deletion src/contentScripts/searchBar/app/SearchResult/style.less
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@
transition: background-color 300ms ease-in-out;
}

.selected {
background: @item-hover-bg;
}
[theme='light'] {
.row:hover {
background: @item-hover-bg;
//.selected;
}
}

Expand Down
102 changes: 53 additions & 49 deletions src/contentScripts/searchBar/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Button, Space } from 'antd';
import useSearchBarService, { SearchBarService } from './useSearchBarService';
import { SearchService, useSearchService } from './useSearchService';
import { useCheckTokenValidService } from './useCheckTokenValidService';
import { KeyboardService, useKeyboardService } from './useKeyboardService';

import SearchInput from './SearchInput';
import SearchResult from './SearchResult';
Expand All @@ -19,58 +20,61 @@ const SearchBar: FC = () => {

const valid = useCheckTokenValidService();

const keyboardService = useKeyboardService();
return visible ? (
<div className={styles.container}>
<div ref={searchBarRef} className={styles.bar}>
{valid ? (
<>
<div className={styles.input}>
<SearchInput />
</div>
<div className={styles.result}>
<AnimatedHeight maxHeight={400}>
<SearchResult />
</AnimatedHeight>
</div>
</>
) : (
<Space direction={'vertical'} className={styles.invalid}>
<div>
<img
src="https://gw.alipayobjects.com/mdn/rms_15e52e/afts/img/A*TJ7dTIRWjVoAAAAAAAAAAAAAARQnAQ"
alt="无效的 token"
/>
</div>
<div style={{ marginTop: 16 }}>
<h3>Token 无效</h3>
</div>
<div style={{ width: 400, textAlign: 'center' }}>
没有配置 token 或 token 无效,请前往配置页添加 token。
添加完成后请刷新页面并重试。
</div>
<Space style={{ marginTop: 16 }}>
<Button
onClick={() => {
window.open(
'https://www.yuque.com/design-engineering/power-yuque/add-token',
);
}}
>
查看教程
</Button>
<Button
type={'primary'}
onClick={() => {
chrome.runtime.sendMessage({ action: 'openOptionsPage' });
}}
>
立即添加
</Button>
<KeyboardService.Provider value={keyboardService}>
<div className={styles.container}>
<div ref={searchBarRef} className={styles.bar}>
{valid ? (
<>
<div className={styles.input}>
<SearchInput />
</div>
<div className={styles.result}>
<AnimatedHeight maxHeight={400}>
<SearchResult />
</AnimatedHeight>
</div>
</>
) : (
<Space direction={'vertical'} className={styles.invalid}>
<div>
<img
src="https://gw.alipayobjects.com/mdn/rms_15e52e/afts/img/A*TJ7dTIRWjVoAAAAAAAAAAAAAARQnAQ"
alt="无效的 token"
/>
</div>
<div style={{ marginTop: 16 }}>
<h3>Token 无效</h3>
</div>
<div style={{ width: 400, textAlign: 'center' }}>
没有配置 token 或 token 无效,请前往配置页添加 token。
添加完成后请刷新页面并重试。
</div>
<Space style={{ marginTop: 16 }}>
<Button
onClick={() => {
window.open(
'https://www.yuque.com/design-engineering/power-yuque/add-token',
);
}}
>
查看教程
</Button>
<Button
type={'primary'}
onClick={() => {
chrome.runtime.sendMessage({ action: 'openOptionsPage' });
}}
>
立即添加
</Button>
</Space>
</Space>
</Space>
)}
)}
</div>
</div>
</div>
</KeyboardService.Provider>
) : null;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,52 @@ import { useContext, useEffect, useRef, useState } from 'react';
import type { Input } from 'antd';

import { getServiceToken } from '@/utils';
import { SearchService } from '../useSearchService';
import { SearchBarService } from '../useSearchBarService';

import { SearchService } from './useSearchService';
import { SearchBarService } from './useSearchBarService';

/**
* Keyboard 需要的状态
*/
export const useKeyboardService = () => {
const { setType, optionKeys, optionActiveIndex, isEmpty } = useContext(
SearchService,
);
const {
setType,
optionKeys,
optionActiveIndex,
isEmpty,
result,
} = useContext(SearchService);
const { hide } = useContext(SearchBarService);

const [focusKey, setFocusKey] = useState<SearchBar.FocusType>('input');
const inputRef = useRef<Input>(null);
const [selectResultIndex, setSelectResultIndex] = useState(0);

const handleIndex = (index: number, length: number, back?: boolean) => {
if (back) {
return index === 0 ? length - 1 : index - 1;
}
return index === length - 1 ? 0 : index + 1;
};
/**
* 按 Tabs 键切换选中 type
* @param back
*/
const switchOptionIndex = (back?: boolean) => {
let newIndex: number;

if (back) {
newIndex =
optionActiveIndex === 0 ? optionKeys.length - 1 : optionActiveIndex - 1;
} else {
newIndex =
optionActiveIndex === optionKeys.length - 1 ? 0 : optionActiveIndex + 1;
}
const newIndex = handleIndex(optionActiveIndex, optionKeys.length, back);

setType(optionKeys[newIndex]);
};

/**
* 按 上下键切换选中的 result
* @param back
*/
const switchResultIndex = (back?: boolean) => {
const newIndex = handleIndex(selectResultIndex, result.length, back);
setSelectResultIndex(newIndex);
};

const focusOnInput = () => {
inputRef.current?.focus();
setFocusKey('input');
Expand All @@ -48,6 +61,11 @@ export const useKeyboardService = () => {
setFocusKey('result');
};

const handleResultIndex = (index: number) => {
focusOnResult();
setSelectResultIndex(index);
};

// 将焦点切换到 Options
const onKeyDown = (event: KeyboardEvent) => {
// 焦点在 options 的情况
Expand All @@ -65,6 +83,10 @@ export const useKeyboardService = () => {
case 'ArrowLeft':
switchOptionIndex(true);
break;
case 'ArrowDown':
event.preventDefault();
focusOnResult();
break;
case 'ArrowUp':
case 'Escape':
focusOnInput();
Expand Down Expand Up @@ -95,6 +117,37 @@ export const useKeyboardService = () => {
default:
}
}

if (focusKey === 'result') {
switch (event.key) {
case 'Tab':
event.preventDefault();
switchOptionIndex(event.shiftKey);
break;
case 'ArrowDown':
event.preventDefault();
switchResultIndex();
break;
case 'ArrowUp':
event.preventDefault();
if (selectResultIndex === 0) {
focusOnOptions();
} else {
switchResultIndex(true);
}
break;
case 'ArrowRight':
switchOptionIndex();
break;
case 'ArrowLeft':
switchOptionIndex(true);
break;
case 'Escape':
focusOnInput();
break;
default:
}
}
};

useEffect(() => {
Expand All @@ -103,12 +156,13 @@ export const useKeyboardService = () => {
return () => {
window.onkeydown = null;
};
}, [focusKey, optionActiveIndex, isEmpty]);
}, [focusKey, optionActiveIndex, isEmpty, selectResultIndex]);

return {
focusKey,
inputRef,

selectResultIndex,
handleResultIndex,
onKeyDown,
focusOnInput,
focusOnOptions,
Expand Down
Loading

0 comments on commit fe4cfec

Please sign in to comment.