mirror of
https://github.com/gethomepage/homepage.git
synced 2026-09-26 05:51:17 -07:00
Fix QL Copilot thing
This commit is contained in:
@@ -15,6 +15,16 @@ const MOBILE_BUTTON_POSITIONS = {
|
|||||||
"bottom-right": "bottom-4 right-4",
|
"bottom-right": "bottom-4 right-4",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function parseUrl(searchString) {
|
||||||
|
if (!/.+[.:].+/.test(searchString)) return null; // basic test for probably a url
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new URL(searchString.toLowerCase().startsWith("http") ? searchString : `https://${searchString}`);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getSearchResults({
|
function getSearchResults({
|
||||||
hideVisitURL,
|
hideVisitURL,
|
||||||
searchDescriptions,
|
searchDescriptions,
|
||||||
@@ -77,7 +87,7 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea
|
|||||||
const searchField = useRef();
|
const searchField = useRef();
|
||||||
|
|
||||||
const [currentItemIndex, setCurrentItemIndex] = useState(null);
|
const [currentItemIndex, setCurrentItemIndex] = useState(null);
|
||||||
const [url, setUrl] = useState(null);
|
const url = parseUrl(searchString);
|
||||||
const [searchSuggestions, setSearchSuggestions] = useState([]);
|
const [searchSuggestions, setSearchSuggestions] = useState([]);
|
||||||
|
|
||||||
const { data: widgets } = useSWR("/api/widgets");
|
const { data: widgets } = useSWR("/api/widgets");
|
||||||
@@ -134,17 +144,8 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea
|
|||||||
function handleSearchChange(event) {
|
function handleSearchChange(event) {
|
||||||
const rawSearchString = event.target.value;
|
const rawSearchString = event.target.value;
|
||||||
setCurrentItemIndex(null);
|
setCurrentItemIndex(null);
|
||||||
try {
|
// urls keep their casing, everything else is lowercased for matching
|
||||||
if (!/.+[.:].+/g.test(rawSearchString)) throw new Error(); // basic test for probably a url
|
setSearchString(parseUrl(rawSearchString) ? rawSearchString : rawSearchString.toLowerCase());
|
||||||
let urlString = rawSearchString;
|
|
||||||
if (urlString.toLowerCase().indexOf("http") !== 0) urlString = `https://${rawSearchString}`;
|
|
||||||
setUrl(new URL(urlString)); // basic validation
|
|
||||||
setSearchString(rawSearchString);
|
|
||||||
return;
|
|
||||||
} catch (e) {
|
|
||||||
setUrl(null);
|
|
||||||
}
|
|
||||||
setSearchString(rawSearchString.toLowerCase());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSearchKeyDown(event) {
|
function handleSearchKeyDown(event) {
|
||||||
|
|||||||
@@ -46,13 +46,25 @@ function Wrapper({ servicesAndBookmarks = [], initialOpen = true } = {}) {
|
|||||||
const [isOpen, setSearching] = useState(initialOpen);
|
const [isOpen, setSearching] = useState(initialOpen);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QuickLaunch
|
<>
|
||||||
servicesAndBookmarks={servicesAndBookmarks}
|
<button
|
||||||
searchString={searchString}
|
type="button"
|
||||||
setSearchString={setSearchString}
|
data-testid="seed-key"
|
||||||
isOpen={isOpen}
|
onClick={() => {
|
||||||
setSearching={setSearching}
|
setSearchString((current) => `${current}g`);
|
||||||
/>
|
setSearching(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
seed
|
||||||
|
</button>
|
||||||
|
<QuickLaunch
|
||||||
|
servicesAndBookmarks={servicesAndBookmarks}
|
||||||
|
searchString={searchString}
|
||||||
|
setSearchString={setSearchString}
|
||||||
|
isOpen={isOpen}
|
||||||
|
setSearching={setSearching}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +163,35 @@ describe("components/quicklaunch", () => {
|
|||||||
openSpy.mockRestore();
|
openSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not carry a previous url result into a search seeded by a keypress", async () => {
|
||||||
|
renderWithProviders(<Wrapper />, {
|
||||||
|
settings: {
|
||||||
|
target: "_self",
|
||||||
|
quicklaunch: {
|
||||||
|
provider: "duckduckgo",
|
||||||
|
showSearchSuggestions: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const input = screen.getByPlaceholderText("Search");
|
||||||
|
await waitFor(() => expect(input).toHaveFocus());
|
||||||
|
|
||||||
|
fireEvent.change(input, { target: { value: "example.com" } });
|
||||||
|
expect(await screen.findByText("quicklaunch.visit URL")).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.keyDown(input, { key: "Escape" });
|
||||||
|
await act(async () => {
|
||||||
|
await new Promise((r) => setTimeout(r, 350));
|
||||||
|
});
|
||||||
|
|
||||||
|
// reopen by "typing" a character, the way pages/index does
|
||||||
|
fireEvent.click(screen.getByTestId("seed-key"));
|
||||||
|
|
||||||
|
expect(input).toHaveValue("g");
|
||||||
|
expect(screen.queryByText("quicklaunch.visit URL")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it("closes on Escape and clears the search string after the timeout", async () => {
|
it("closes on Escape and clears the search string after the timeout", async () => {
|
||||||
renderWithProviders(<Wrapper />, {
|
renderWithProviders(<Wrapper />, {
|
||||||
settings: {
|
settings: {
|
||||||
|
|||||||
Reference in New Issue
Block a user