feature: better base64NLP, add copy to clipboard for text

This commit is contained in:
Alikia2x 2024-04-26 22:20:49 +08:00
parent b46f1adddb
commit 86d4015ae5
8 changed files with 1674 additions and 1400 deletions

View File

@ -1,14 +1,26 @@
import { settingsType, suggestionItem } from "@/global"; import { settingsType, suggestionItem } from "@/global";
import copyToClipboard from "@/lib/copy";
import { normalizeURL } from "@/lib/normalizeURL"; import { normalizeURL } from "@/lib/normalizeURL";
import search from "@/lib/search"; import search from "@/lib/search";
export default function (index: number, suggestion: suggestionItem[], query: string, settings: settingsType) { export default function (
index: number,
suggestion: suggestionItem[],
query: string,
settings: settingsType,
searchBoxRef: React.RefObject<HTMLInputElement>
) {
const selected = suggestion[index]; const selected = suggestion[index];
const engine = settings.searchEngines[settings.currentSearchEngine]; const engine = settings.searchEngines[settings.currentSearchEngine];
const newTab = settings.searchInNewTab; const newTab = settings.searchInNewTab;
let clipboard: any;
if (selected.type === "QUERY" || selected.type === "default") { if (selected.type === "QUERY" || selected.type === "default") {
search(selected.suggestion, engine, newTab); search(selected.suggestion, engine, newTab);
} else if (selected.type === "NAVIGATION") { } else if (selected.type === "NAVIGATION") {
window.open(normalizeURL(selected.suggestion)); window.open(normalizeURL(selected.suggestion));
} else if (selected.type === "text") {
console.log("????");
copyToClipboard(selected.suggestion);
searchBoxRef.current?.focus();
} }
} }

View File

@ -36,12 +36,11 @@ export default function () {
.then((res) => res.json()) .then((res) => res.json())
.then((data: suggestionsResponse) => { .then((data: suggestionsResponse) => {
let suggestionToUpdate: suggestionItem[] = data.suggestions; let suggestionToUpdate: suggestionItem[] = data.suggestions;
if (data.time > lastRequestTimeRef.current){ if (data.time > lastRequestTimeRef.current) {
cleanSuggestion("NAVIGATION", "QUERY"); cleanSuggestion("NAVIGATION", "QUERY");
lastRequestTimeRef.current = data.time; lastRequestTimeRef.current = data.time;
updateSuggestion(suggestionToUpdate); updateSuggestion(suggestionToUpdate);
} }
}); });
}, [query]); }, [query]);
@ -71,14 +70,13 @@ export default function () {
} }
useEffect(() => { useEffect(() => {
cleanSuggestion("default-link", "default", "text");
if (validLink(query)) { if (validLink(query)) {
cleanSuggestion("default-link","default","text")
updateSuggestion([ updateSuggestion([
{ type: "default-link", suggestion: query, relevance: 3000 }, { type: "default-link", suggestion: query, relevance: 3000 },
{ type: "default", suggestion: query, relevance: 1600 } { type: "default", suggestion: query, relevance: 1600 }
]); ]);
} else { } else {
cleanSuggestion("default-link","default","text")
updateSuggestion([ updateSuggestion([
{ {
type: "default", type: "default",
@ -88,8 +86,8 @@ export default function () {
]); ]);
} }
const b64 = base64NLP(query); const b64 = base64NLP(query);
if (b64.suggestion!==null){ console.log(base64NLP(query));
cleanSuggestion("default-link","default","text") if (b64.suggestion !== null) {
updateSuggestion([b64 as suggestionItem]); updateSuggestion([b64 as suggestionItem]);
} }
}, [query, engineName]); }, [query, engineName]);
@ -125,11 +123,7 @@ export default function () {
); );
} else if (s.type === "NAVIGATION" || s.type === "default-link") { } else if (s.type === "NAVIGATION" || s.type === "default-link") {
return ( return (
<Link <Link key={i} query={s.suggestion} selected={i == selected}>
key={i}
query={s.suggestion}
selected={i == selected}
>
{s.suggestion} {s.suggestion}
{devMode && ( {devMode && (
<span className="text-zinc-700 dark:text-zinc-400 text-sm"> <span className="text-zinc-700 dark:text-zinc-400 text-sm">
@ -148,7 +142,7 @@ export default function () {
</span> </span>
)} )}
</PlainText> </PlainText>
) );
} }
})} })}
</SuggestionBox> </SuggestionBox>

View File

@ -8,7 +8,7 @@ import { settingsType } from "@/global";
import handleEnter from "./onesearch/handleEnter"; import handleEnter from "./onesearch/handleEnter";
import { selectedSuggestionState } from "../state/suggestionSelection"; import { selectedSuggestionState } from "../state/suggestionSelection";
import { suggestionsState } from "../state/suggestion"; import { suggestionsState } from "../state/suggestion";
import { KeyboardEvent } from "react"; import { KeyboardEvent, useRef } from "react";
export default function Search(props: { onFocus: () => void }) { export default function Search(props: { onFocus: () => void }) {
const settings: settingsType = useRecoilValue(settingsState); const settings: settingsType = useRecoilValue(settingsState);
@ -16,13 +16,14 @@ export default function Search(props: { onFocus: () => void }) {
const [query, setQuery] = useRecoilState(queryState); const [query, setQuery] = useRecoilState(queryState);
const [selectedSuggestion, setSelected] = useRecoilState(selectedSuggestionState); const [selectedSuggestion, setSelected] = useRecoilState(selectedSuggestionState);
const suggestions = useRecoilValue(suggestionsState); const suggestions = useRecoilValue(suggestionsState);
const searchBoxRef = useRef<HTMLInputElement>(null);
let style = "default"; let style = "default";
function handleKeydown(e: KeyboardEvent) { function handleKeydown(e: KeyboardEvent) {
if (e.key == "Enter") { if (e.key == "Enter") {
e.preventDefault(); e.preventDefault();
handleEnter(selectedSuggestion, suggestions, query, settings); handleEnter(selectedSuggestion, suggestions, query, settings, searchBoxRef);
return; return;
} else if (e.key == "ArrowUp") { } else if (e.key == "ArrowUp") {
e.preventDefault(); e.preventDefault();
@ -58,6 +59,7 @@ export default function Search(props: { onFocus: () => void }) {
autoCorrect="off" autoCorrect="off"
autoCapitalize="off" autoCapitalize="off"
spellCheck="false" spellCheck="false"
ref={searchBoxRef}
value={query} value={query}
/> />
</div> </div>
@ -81,6 +83,7 @@ export default function Search(props: { onFocus: () => void }) {
type="text" type="text"
placeholder={t("placeholder")} placeholder={t("placeholder")}
onFocus={props.onFocus} onFocus={props.onFocus}
ref={searchBoxRef}
/> />
</div> </div>
); );

8
lib/copy.ts Normal file
View File

@ -0,0 +1,8 @@
export default function copyToClipboard(value: string){
const textarea = document.createElement("textarea");
textarea.value = value;
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
};

View File

@ -1,7 +1,8 @@
const stopwords = ["a","about","above","after","again","against","all","am","an","and","any","are","aren't","as","at","be","because","been","before","being","below","between","both","but","by","can't","cannot","could","couldn't","did","didn't","do","does","doesn't","doing","don't","down","during","each","few","for","from","further","had","hadn't","has","hasn't","have","haven't","having","he","he'd","he'll","he's","her","here","here's","hers","herself","him","himself","his","how","how's","i","i'd","i'll","i'm","i've","if","in","into","is","isn't","it","it's","its","itself","let's","me","more","most","mustn't","my","myself","no","nor","not","of","off","on","once","only","or","other","ought","our","ours ourselves","out","over","own","same","shan't","she","she'd","she'll","she's","should","shouldn't","so","some","such","than","that","that's","the","their","theirs","them","themselves","then","there","there's","these","they","they'd","they'll","they're","they've","this","those","through","to","too","under","until","up","very","was","wasn't","we","we'd","we'll","we're","we've","were","weren't","what","what's","when","when's","where","where's","which","while","who","who's","whom","why","why's","with","won't","would","wouldn't","you","you'd","you'll","you're","you've","your","yours","yourself","yourselves"]; const stopwords = ["a","about","above","after","again","against","all","am","an","and","any","are","aren't","as","at","be","because","been","before","being","below","between","both","but","by","can't","cannot","could","couldn't","did","didn't","do","does","doesn't","doing","don't","down","during","each","few","for","from","further","had","hadn't","has","hasn't","have","haven't","having","he","he'd","he'll","he's","her","here","here's","hers","herself","him","himself","his","how","how's","i","i'd","i'll","i'm","i've","if","in","into","is","isn't","it","it's","its","itself","let's","me","more","most","mustn't","my","myself","no","nor","not","of","off","on","once","only","or","other","ought","our","ours ourselves","out","over","own","same","shan't","she","she'd","she'll","she's","should","shouldn't","so","some","such","than","that","that's","the","their","theirs","them","themselves","then","there","there's","these","they","they'd","they'll","they're","they've","this","those","through","to","too","under","until","up","very","was","wasn't","we","we'd","we'll","we're","we've","were","weren't","what","what's","when","when's","where","where's","which","while","who","who's","whom","why","why's","with","won't","would","wouldn't","you","you'd","you'll","you're","you've","your","yours","yourself","yourselves"];
export default function removeStopwords(str: string, extraStopwords: string[] = []){ export default function removeStopwords(str: string, extraStopwords: string[] = [], disableDefault: boolean = false){
for (let word of stopwords.concat(extraStopwords)){ const list = disableDefault ? extraStopwords : stopwords.concat(extraStopwords);
for (let word of list){
str = str.replace(new RegExp(`\\b${word}\\b`, 'gi'), ''); str = str.replace(new RegExp(`\\b${word}\\b`, 'gi'), '');
} }
return str; return str;

View File

@ -46,7 +46,7 @@ export function base64NLP(str: string) {
let processedQuery = ""; let processedQuery = "";
if (result.intention==="base64.encode"){ if (result.intention==="base64.encode"){
processedQuery = str.split(" ")[str.split(" ").length-1]; processedQuery = removeStopwords(str, Object.keys(keywords).concat(Object.keys(intentions)), true).trim();
} else if (result.intention==="base64.decode") { } else if (result.intention==="base64.decode") {
processedQuery = removeStopwords(str, Object.keys(keywords).concat(Object.keys(intentions))).trim(); processedQuery = removeStopwords(str, Object.keys(keywords).concat(Object.keys(intentions))).trim();
} }

View File

@ -10,18 +10,18 @@
"test": "jest" "test": "jest"
}, },
"dependencies": { "dependencies": {
"@nextui-org/react": "^2.2.10", "@nextui-org/react": "^2.3.6",
"clsx": "^2.1.0", "clsx": "^2.1.1",
"framer-motion": "^11.0.25", "framer-motion": "^11.1.7",
"next": "14.1.4", "next": "14.1.4",
"next-intl": "^3.11.1", "next-intl": "^3.12.0",
"next-themes": "^0.3.0", "next-themes": "^0.3.0",
"punycode": "^2.3.1", "punycode": "^2.3.1",
"react": "^18.2.0", "react": "^18.3.0",
"react-dom": "^18.2.0", "react-dom": "^18.3.0",
"recoil": "^0.7.7", "recoil": "^0.7.7",
"search-engine-autocomplete": "^0.4.3", "search-engine-autocomplete": "^0.4.3",
"tailwind-merge": "^2.2.2", "tailwind-merge": "^2.3.0",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"valid-url": "^1.0.9", "valid-url": "^1.0.9",
"validate-color": "^2.2.4" "validate-color": "^2.2.4"
@ -29,12 +29,12 @@
"devDependencies": { "devDependencies": {
"@jest/globals": "^29.7.0", "@jest/globals": "^29.7.0",
"@testing-library/jest-dom": "^6.4.2", "@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.3.0", "@testing-library/react": "^14.3.1",
"@types/jest": "^29.5.12", "@types/jest": "^29.5.12",
"@types/node": "^20.12.7", "@types/node": "^20.12.7",
"@types/punycode": "^2.1.4", "@types/punycode": "^2.1.4",
"@types/react": "^18.2.75", "@types/react": "^18.3.0",
"@types/react-dom": "^18.2.24", "@types/react-dom": "^18.3.0",
"@types/valid-url": "^1.0.7", "@types/valid-url": "^1.0.7",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"jest": "^29.7.0", "jest": "^29.7.0",
@ -42,6 +42,6 @@
"postcss": "^8.4.38", "postcss": "^8.4.38",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"ts-jest": "^29.1.2", "ts-jest": "^29.1.2",
"typescript": "^5.4.4" "typescript": "^5.4.5"
} }
} }

File diff suppressed because it is too large Load Diff