Skip to content

Commit 6f86707

Browse files
committed
feat: support caching of query results
1 parent f783023 commit 6f86707

File tree

6 files changed

+92
-16
lines changed

6 files changed

+92
-16
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
],
3939
"dependencies": {
4040
"@raycast/api": "^1.48.9",
41+
"@types/lodash": "^4.14.191",
4142
"change-case": "^4.1.2",
43+
"lodash": "^4.17.21",
4244
"node-fetch": "^3.3.1"
4345
},
4446
"devDependencies": {

src/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* The unique key for LocalStorage
3+
*/
4+
export const CODE_VAR_HISTORY = "CODE_VAR_HISTORY";
5+
16
/**
27
* Turn on the type of query needed on demand
38
*/

src/index.tsx

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React from "react";
2+
import { debounce } from "lodash";
23
import { Action, ActionPanel, List, Icon, Clipboard, showToast, Toast } from "@raycast/api";
4+
import { queryVariableNames, getHistory, deleteAllHistory, deleteHistoryItem } from "./useQuery";
35
import type { Result } from "./types";
4-
import { queryVariableNames } from "./useQuery";
56

67
export default function Command() {
78
const cancelRef = React.useRef<AbortController | null>(null);
@@ -14,12 +15,19 @@ export default function Command() {
1415
};
1516
}, []);
1617

17-
const onSearchTextChange = async (searchContent: string) => {
18+
const onSearchTextChange = async (text: string) => {
1819
cancelRef.current?.abort();
20+
const searchContent = text.trim();
1921
if (!searchContent) {
2022
setVariableNames([]);
2123
return;
2224
}
25+
const cache = await getHistory(searchContent);
26+
if (cache.length > 0) {
27+
setVariableNames(cache);
28+
setLoading(false);
29+
return;
30+
}
2331
cancelRef.current = new AbortController();
2432
try {
2533
setLoading(true);
@@ -41,16 +49,15 @@ export default function Command() {
4149
return (
4250
<List
4351
isLoading={loading}
44-
onSearchTextChange={onSearchTextChange}
52+
onSearchTextChange={debounce(onSearchTextChange, 500, { trailing: true })}
4553
searchBarPlaceholder="Please enter variable name"
46-
throttle
4754
>
4855
{variableNames.map((variableName) => (
4956
<List.Item
5057
key={variableName.type}
5158
title={variableName.value}
5259
subtitle={variableName.type}
53-
icon={Icon.Stars}
60+
icon={variableName.query ? Icon.Clock : Icon.Stars}
5461
actions={
5562
<ActionPanel>
5663
<ActionPanel.Section>
@@ -61,6 +68,26 @@ export default function Command() {
6168
icon={{ source: Icon.CopyClipboard }}
6269
/>
6370
</ActionPanel.Section>
71+
72+
<ActionPanel.Section title="History">
73+
{variableName.query && (
74+
<Action
75+
title="Remove From History"
76+
onAction={async () => {
77+
await deleteHistoryItem(variableName);
78+
}}
79+
icon={{ source: Icon.Trash }}
80+
shortcut={{ modifiers: ["cmd"], key: "d" }}
81+
/>
82+
)}
83+
<Action
84+
title="Clear All History"
85+
onAction={async () => {
86+
await deleteAllHistory();
87+
}}
88+
icon={{ source: Icon.ExclamationMark }}
89+
/>
90+
</ActionPanel.Section>
6491
</ActionPanel>
6592
}
6693
/>

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { CASES } from "./constants";
33
export interface Result {
44
value: string;
55
type: (typeof CASES)[number];
6+
query?: string;
67
}
78

89
export interface ChatCompletion {

src/useQuery.ts

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,36 @@
11
import * as changeCase from "change-case";
2-
import { LocalStorage, getPreferenceValues } from "@raycast/api";
2+
import { LocalStorage, getPreferenceValues, showToast, Toast } from "@raycast/api";
33
import fetch from "node-fetch";
44

5-
import { CASES } from "./constants";
5+
import { CASES, CODE_VAR_HISTORY } from "./constants";
66
import type { Result, ChatCompletion } from "./types";
77

8-
// todo:Return results directly from query history
9-
export async function getSearchHistory(): Promise<Result[]> {
10-
const historyString = (await LocalStorage.getItem("history")) as string;
8+
export async function getHistory(queryText: string): Promise<Result[]> {
9+
const historyString = (await LocalStorage.getItem(`${CODE_VAR_HISTORY}_${queryText}`)) as string;
1110
if (historyString === undefined) return [];
1211
const items: Result[] = JSON.parse(historyString);
1312
return items;
1413
}
1514

16-
export async function queryVariableNames(content: string, signal?: AbortSignal): Promise<Result[]> {
15+
export async function deleteAllHistory() {
16+
await LocalStorage.clear();
17+
showToast({
18+
style: Toast.Style.Success,
19+
title: "Success",
20+
message: "Cleared search history",
21+
});
22+
}
23+
24+
export async function deleteHistoryItem(result: Result) {
25+
await LocalStorage.removeItem(`${CODE_VAR_HISTORY}_${result.query}`);
26+
showToast({
27+
style: Toast.Style.Success,
28+
title: "Success",
29+
message: "Removed from history",
30+
});
31+
}
32+
33+
export async function queryVariableNames(queryText: string, signal?: AbortSignal): Promise<Result[]> {
1734
const { entrypoint, apiKey } = getPreferenceValues<{ entrypoint: string; apiKey: string }>();
1835

1936
const response = await fetch(entrypoint, {
@@ -28,7 +45,7 @@ export async function queryVariableNames(content: string, signal?: AbortSignal):
2845
messages: [
2946
{
3047
role: "user",
31-
content: `Translate to en: \n\n ${content}`,
48+
content: `Translate to en: \n\n ${queryText}`,
3249
},
3350
],
3451
}),
@@ -41,15 +58,29 @@ export async function queryVariableNames(content: string, signal?: AbortSignal):
4158
let result: Result[] = [];
4259
try {
4360
const text = (content?.choices?.[0]?.message?.content || "").replace(/\n/g, "").replace(/\./g, "").trim();
44-
result = CASES.map((type) => {
45-
if (type === "capitalCase") {
46-
return { value: changeCase[type](text.replace(/ /g, "")), type };
61+
result = CASES.map((caseType) => {
62+
if (caseType === "capitalCase") {
63+
return {
64+
value: changeCase[caseType](text.replace(/ /g, "")),
65+
type: caseType,
66+
};
4767
}
48-
return { value: changeCase[type](text), type };
68+
return {
69+
value: changeCase[caseType](text),
70+
type: caseType,
71+
};
4972
});
5073
} catch (error) {
5174
result = [];
5275
}
76+
77+
if (queryText && result.length > 0) {
78+
await LocalStorage.setItem(
79+
`${CODE_VAR_HISTORY}_${queryText}`,
80+
JSON.stringify(result.map((item) => ({ ...item, query: queryText })))
81+
);
82+
}
83+
5384
return result;
5485
}
5586
}

yarn.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@
124124
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
125125
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
126126

127+
"@types/lodash@^4.14.191":
128+
version "4.14.191"
129+
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa"
130+
integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==
131+
127132
128133
version "18.8.3"
129134
resolved "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz#ce750ab4017effa51aed6a7230651778d54e327c"
@@ -877,6 +882,11 @@ lodash.truncate@^4.4.2:
877882
resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
878883
integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
879884

885+
lodash@^4.17.21:
886+
version "4.17.21"
887+
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
888+
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
889+
880890
loose-envify@^1.1.0:
881891
version "1.4.0"
882892
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"

0 commit comments

Comments
 (0)