Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions i18n/english.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ const ui = {
placeholder: "Search packages...",
placeholder_filter_hint: "or use",
placeholder_refine: "Add another filter...",
section_actions: "Actions",
action_toggle_theme_to_dark: "Switch to dark theme",
action_toggle_theme_to_light: "Switch to light theme",
section_presets: "Quick filters",
preset_has_vulnerabilities: "Has vulnerabilities",
preset_has_scripts: "Has install scripts",
Expand Down
3 changes: 3 additions & 0 deletions i18n/french.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ const ui = {
placeholder: "Rechercher des packages...",
placeholder_filter_hint: "ou utiliser",
placeholder_refine: "Ajouter un autre filtre...",
section_actions: "Actions",
action_toggle_theme_to_dark: "Passer en thème sombre",
action_toggle_theme_to_light: "Passer en thème clair",
section_presets: "Filtres rapides",
preset_has_vulnerabilities: "Contient des vulnérabilités",
preset_has_scripts: "Scripts d'installation",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,32 @@ export function renderPresets({ presets, onApply }) {
`;
}

/**
* @param {{ actions: Array<{ id: string, label: string, kbd: string|null }>, onExecute: Function }} props
*/
export function renderActions({ actions, onExecute }) {
const i18n = window.i18n[currentLang()].search_command;

return html`
<div class="section">
<div class="section-title">${i18n.section_actions}</div>
<div class="range-panel">
<div class="range-presets">
${actions.map((action) => html`
<button
class="range-preset"
@click=${() => onExecute(action)}
>
${action.label}
${action.kbd ? html`<kbd class="action-kbd">${action.kbd}</kbd>` : nothing}
</button>
`)}
</div>
</div>
</div>
`;
}

/**
* @param {{ results: Array, selectedIndex: number, helperCount: number, onFocus: Function }} props
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { css } from "lit";
// Import Internal Dependencies
import { scrollbarStyle } from "../../common/scrollbar-style.js";

export const searchCommandStyles = [
export const commandPaletteStyles = [
scrollbarStyle,
css`
:host {
Expand Down Expand Up @@ -380,5 +380,11 @@ kbd {
font-size: 11px;
color: var(--sc-kbd-text);
}

.action-kbd {
margin-left: 6px;
opacity: 0.7;
border: 1px solid var(--sc-border);
}
`
];
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,39 @@ import {
computeMatches,
getHelperValues
} from "./filters.js";
import { searchCommandStyles } from "./search-command-styles.js";
import { commandPaletteStyles } from "./command-palette-styles.js";
import {
renderFlagPanel,
renderRangePanel,
renderListPanel,
renderFilterList,
renderPresets,
renderActions,
renderResults
} from "./search-command-panels.js";
} from "./command-palette-panels.js";
import "./search-chip.js";

class SearchCommand extends LitElement {
// CONSTANTS
const kActions = [
{ id: "toggle_theme", shortcut: "t" }
];

function resolveKbd(shortcut) {
if (!shortcut) {
return null;
}

const key = shortcut.toUpperCase();

return navigator.userAgent.includes("Mac") ? `⌥${key}` : `Alt+${key}`;
}

class CommandPalette extends LitElement {
#linker = null;
#network = null;
#packages = [];

static styles = searchCommandStyles;
static styles = commandPaletteStyles;

static properties = {
open: { type: Boolean },
Expand All @@ -55,6 +71,16 @@ class SearchCommand extends LitElement {

if (event.key === "Escape" && this.open) {
this.#close();

return;
}

if (this.open && event.altKey) {
const action = kActions.find((a) => a.shortcut && `Key${a.shortcut.toUpperCase()}` === event.code);
if (action) {
event.preventDefault();
this.#executeAction(action);
}
}
};

Expand Down Expand Up @@ -84,12 +110,12 @@ class SearchCommand extends LitElement {
connectedCallback() {
super.connectedCallback();
document.addEventListener("keydown", this.#handleKeydown);
window.addEventListener(EVENTS.SEARCH_COMMAND_INIT, this.#init);
window.addEventListener(EVENTS.COMMAND_PALETTE_INIT, this.#init);
}

disconnectedCallback() {
document.removeEventListener("keydown", this.#handleKeydown);
window.removeEventListener(EVENTS.SEARCH_COMMAND_INIT, this.#init);
window.removeEventListener(EVENTS.COMMAND_PALETTE_INIT, this.#init);
super.disconnectedCallback();
}

Expand Down Expand Up @@ -323,6 +349,17 @@ class SearchCommand extends LitElement {
this.#close();
}

#executeAction(action) {
if (action.id === "toggle_theme") {
const nextTheme = window.settings.config.theme === "dark" ? "light" : "dark";
window.dispatchEvent(new CustomEvent(EVENTS.SETTINGS_SAVED, {
detail: { ...window.settings.config, theme: nextTheme }
}));
}

this.#close();
}

#getEmptyQueryMessage() {
const i18n = window.i18n[currentLang()].search_command;
if (this.queries.length === 1) {
Expand Down Expand Up @@ -407,6 +444,20 @@ class SearchCommand extends LitElement {
}
}

#resolveActions() {
const i18n = window.i18n[currentLang()].search_command;
const currentTheme = window.settings?.config?.theme ?? "light";
const targetTheme = currentTheme === "dark" ? "light" : "dark";

return kActions.map((action) => {
return {
...action,
label: i18n[`action_${action.id}_to_${targetTheme}`],
kbd: resolveKbd(action.shortcut)
};
});
}

render() {
if (!this.open) {
return nothing;
Expand Down Expand Up @@ -483,6 +534,10 @@ class SearchCommand extends LitElement {
presets: PRESETS,
onApply: (preset) => this.#addQuery(preset.filter, preset.value)
}) : nothing}
${showRichPlaceholder ? renderActions({
actions: this.#resolveActions(),
onExecute: (action) => this.#executeAction(action)
}) : nothing}
${renderResults({
results: this.results,
selectedIndex: this.selectedIndex,
Expand All @@ -505,4 +560,4 @@ class SearchCommand extends LitElement {
}
}

customElements.define("search-command", SearchCommand);
customElements.define("command-palette", CommandPalette);
2 changes: 1 addition & 1 deletion public/components/navigation/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class ViewNavigation {
const isTargetPopup = event.target.id === "popup--background";
const isPopupOpened = document.querySelector("#popup--background.show");
const isTargetInput = event.target.tagName === "INPUT";
const isSearchCommandOpen = Boolean(document.querySelector("search-command")?.open);
const isSearchCommandOpen = Boolean(document.querySelector("command-palette")?.open);
if (isTargetPopup || isWikiOpen || isTargetInput || isPopupOpened || isSearchCommandOpen) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion public/components/wiki/wiki.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class Wiki {
#keydownHotkeys(event) {
const isTargetInput = event.target.tagName === "INPUT";
const isTargetPopup = event.target.id === "popup--background";
const isSearchCommandOpen = Boolean(document.querySelector("search-command")?.open);
const isSearchCommandOpen = Boolean(document.querySelector("command-palette")?.open);
if (isTargetInput || isTargetPopup || isSearchCommandOpen) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion public/core/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const EVENTS = {
MODAL_OPENED: "modal-opened",
NETWORK_VIEW_HID: "network-view-hid",
NETWORK_VIEW_SHOWED: "network-view-showed",
SEARCH_COMMAND_INIT: "search-command-init",
COMMAND_PALETTE_INIT: "command-palette-init",
DRILL_RESET: "drill-reset",
DRILL_BACK: "drill-back",
DRILL_SWITCH: "drill-switch",
Expand Down
2 changes: 1 addition & 1 deletion public/core/network-navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export class NetworkNavigation {
const isWikiOpen = document.getElementById("documentation-root-element").classList.contains("slide-in");
const isTargetPopup = event.target.id === "popup--background";
const isTargetInput = event.target.tagName === "INPUT";
const isSearchCommandOpen = Boolean(document.querySelector("search-command")?.open);
const isSearchCommandOpen = Boolean(document.querySelector("command-palette")?.open);
if (isNetworkViewHidden || isWikiOpen || isTargetPopup || isTargetInput || isSearchCommandOpen) {
return;
}
Expand Down
10 changes: 5 additions & 5 deletions public/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import "./components/popup/popup.js";
import "./components/locker/locker.js";
import "./components/legend/legend.js";
import "./components/locked-navigation/locked-navigation.js";
import "./components/search-command/search-command.js";
import "./components/command-palette/command-palette.js";
import "./components/views/settings/settings.js";
import { HomeView } from "./components/views/home/home.js";
import "./components/views/search/search.js";
Expand Down Expand Up @@ -194,7 +194,7 @@ async function onSocketPayload(event) {
window.navigation.setNavByName(targetView);
}

dispatchSearchCommandInit();
dispatchCommandPaletteInit();
}

async function onSocketInitOrReload(event) {
Expand Down Expand Up @@ -231,15 +231,15 @@ async function onSocketInitOrReload(event) {
window.navigation.setNavByName("search--view");
}

dispatchSearchCommandInit();
dispatchCommandPaletteInit();
}

function dispatchSearchCommandInit() {
function dispatchCommandPaletteInit() {
if (!nsn || !secureDataSet) {
return;
}

const event = new CustomEvent(EVENTS.SEARCH_COMMAND_INIT, {
const event = new CustomEvent(EVENTS.COMMAND_PALETTE_INIT, {
detail: {
network: nsn,
linker: secureDataSet.linker,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Import Third-party Dependencies
import { test, expect } from "@playwright/test";

test.describe("[search-command] presets", () => {
test.describe("[command-palette] presets and actions", () => {
let i18n;

test.beforeEach(async({ page }) => {
Expand All @@ -26,7 +26,13 @@ test.describe("[search-command] presets", () => {
});

test("renders all five preset buttons", async({ page }) => {
await expect(page.locator(".range-preset")).toHaveCount(5);
const presetsSection = page.locator(".section").filter({ hasText: i18n.section_presets });
await expect(presetsSection.locator(".range-preset")).toHaveCount(5);
});

test("renders the theme toggle action button", async({ page }) => {
const actionsSection = page.locator(".section").filter({ hasText: i18n.section_actions });
await expect(actionsSection.locator(".range-preset")).toHaveCount(1);
});

test("clicking a preset adds a chip and hides the presets section", async({ page }) => {
Expand Down Expand Up @@ -55,6 +61,29 @@ test.describe("[search-command] presets", () => {
await expect(page.locator(".empty-state")).toHaveText(i18n.empty_after_filter);
});

test("clicking the theme action closes the palette and toggles the theme", async({ page }) => {
const initialTheme = await page.evaluate(() => window.settings.config.theme);
const expectedTheme = initialTheme === "dark" ? "light" : "dark";

const actionsSection = page.locator(".section").filter({ hasText: i18n.section_actions });
await actionsSection.locator(".range-preset").click();

await expect(page.locator(".backdrop")).not.toBeVisible();
const newTheme = await page.evaluate(() => window.settings.config.theme);
expect(newTheme).toBe(expectedTheme);
});

test("Alt+T triggers the theme toggle and closes the palette", async({ page }) => {
const initialTheme = await page.evaluate(() => window.settings.config.theme);
const expectedTheme = initialTheme === "dark" ? "light" : "dark";

await page.keyboard.press("Alt+t");

await expect(page.locator(".backdrop")).not.toBeVisible();
const newTheme = await page.evaluate(() => window.settings.config.theme);
expect(newTheme).toBe(expectedTheme);
});

test("pressing Escape closes the palette", async({ page }) => {
await page.keyboard.press("Escape");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
getFlagCounts,
getFilterValueCounts,
getHelperValues
} from "../../public/components/search-command/filters.js";
} from "../../public/components/command-palette/filters.js";

const kLinker = new Map([
[0, {
Expand Down
2 changes: 1 addition & 1 deletion views/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@
<section id="package-info"></section>
</section>
</main>
<search-command></search-command>
<command-palette></command-palette>
</html>
Loading