Enable search on all pages

This commit is contained in:
2026-10-02 18:19:42 +02:00
parent 09fa193e9a
commit d5772c24e5
6 changed files with 46 additions and 36 deletions

View File

@@ -11,7 +11,6 @@ import { css_from_path } from "filesystem/edit_window/Branding";
import { update_favicon } from "util/NovaLogo.svelte";
import AffiliatePrompt from "user_home/AffiliatePrompt.svelte";
import { current_page_store } from "wrap/RouterStore";
import SearchBar from "./SearchBar.svelte";
import ErrorPage from "./ErrorPage.svelte";
let file_preview: FilePreview = $state()
@@ -21,7 +20,6 @@ let details_visible = $state(false)
let edit_window: EditWindow = $state()
let edit_visible = $state(false)
let details_window: DetailsWindow = $state()
let search_bar: SearchBar = $state()
const nav = global_navigator
@@ -91,9 +89,6 @@ const keydown = (e: KeyboardEvent) => {
case "r":
nav.shuffle = !nav.shuffle
break;
case "/":
search_bar.open()
break;
case "a":
case "ArrowLeft":
nav.open_sibling(-1)
@@ -156,7 +151,6 @@ const keydown = (e: KeyboardEvent) => {
upload_widget={upload_widget}
edit_window={edit_window}
details_window={details_window}
search_bar={search_bar}
/>
</div>
@@ -173,8 +167,6 @@ const keydown = (e: KeyboardEvent) => {
<ErrorPage nav={nav} />
{/if}
<SearchBar bind:this={search_bar} nav={nav}/>
<DetailsWindow nav={nav} bind:this={details_window} bind:visible={details_visible} />
<EditWindow nav={nav} bind:this={edit_window} bind:visible={edit_visible} />

View File

@@ -1,13 +1,17 @@
<script lang="ts" module>
// The search bar is mounted once, in App.svelte. It sets this function when it
// mounts, so that other components can open it
export let open_search: () => void
</script>
<script lang="ts">
import { onMount, tick } from "svelte";
import { fs_search, fs_encode_path, fs_thumbnail_url, FSNode } from "lib/FilesystemAPI.svelte";
import type { FSNavigator } from "filesystem/FSNavigator";
import { global_navigator as nav } from "filesystem/FSNavigator";
import { loading_finish, loading_start } from "lib/Loading";
import { user } from "lib/UserStore";
import Modal from "util/Modal.svelte";
let { nav }: {
nav: FSNavigator;
} = $props();
import { navigate } from "wrap/Router.svelte";
let modal: Modal
let search_bar: HTMLInputElement = $state()
@@ -32,8 +36,23 @@ onMount(() => {
})
})
export const open = async () => {
search_prefix_node = nav.base
// The path of the directory to search. Outside of the filesystem page the
// navigator is stale or empty, there it's the home directory of the user.
// Visitors who are not logged in don't have one, then the path is empty
const search_path = (): FSNode[] => {
if (nav.initialized && window.location.pathname.startsWith("/d/")) {
// If the base is not a directory, we use the parent
return nav.base.type === "dir" ? nav.path : nav.path.slice(0, -1)
}
return $user === null ? [] : [{name: $user.username, path: "/me"} as FSNode]
}
open_search = async () => {
const path = search_path()
if (path.length === 0) {
return
}
search_prefix_node = path[path.length-1]
modal.show()
await tick()
search_bar.focus()
@@ -62,18 +81,14 @@ const search = async (limit = 10) => {
try {
loading_start()
let search_node = nav.base
// If the base is not a directory, we use the parent
if (search_node.type !== "dir") {
search_node = nav.path[nav.path.length-2]
}
const path = search_path()
let search_node = path[path.length-1]
let search_results_tmp = await fs_search(search_node.path, search_term, limit)
// If there are no results, and we are not searching the filesystem
// root, we will search the filesystem root
if (search_results_tmp.length === 0 && search_node.path != nav.path[0].path) {
search_node = nav.path[0]
if (search_results_tmp.length === 0 && path.length > 1) {
search_node = path[0]
search_results_tmp = await fs_search(search_node.path, search_term, limit)
}
@@ -158,14 +173,14 @@ const open_result = (index: number, e?: MouseEvent) => {
if (e !== undefined) {
e.preventDefault()
}
nav.navigate(search_results[index], true)
navigate("/d" + fs_encode_path(search_results[index]))
clear_search(false)
}
const window_keydown = (e: KeyboardEvent) => {
if (e.ctrlKey || e.altKey || e.metaKey) {
return // prevent custom shortcuts from interfering with system shortcuts
} else if ((document.activeElement as any).type !== undefined && (document.activeElement as any).type === "text") {
} else if (document.activeElement.matches("input, textarea, select")) {
return // Prevent shortcuts from interfering with input fields
}
@@ -175,9 +190,7 @@ const window_keydown = (e: KeyboardEvent) => {
} else if (e.key === "/" || e.key === "f") {
e.preventDefault()
e.stopPropagation()
// search_bar.focus()
open()
return
open_search()
}
}
</script>

View File

@@ -19,7 +19,7 @@ import EditWindow from "filesystem/edit_window/EditWindow.svelte";
import { FileAction, type FileActionHandler } from "./FileManagerLib";
import FileMenu from "./FileMenu.svelte";
import { loading_finish, loading_start } from "lib/Loading";
import SearchBar from "../SearchBar.svelte";
import { open_search } from "../SearchBar.svelte";
import { onMount } from "svelte";
import { toolbar_store } from "wrap/HeaderStore";
@@ -27,14 +27,12 @@ let {
nav = $bindable(),
upload_widget,
edit_window = $bindable(),
search_bar = $bindable(),
directory_view = $bindable(localStorage.getItem("directory_view") || "list"),
children
}: {
nav: FSNavigator;
upload_widget: FsUploadWidget;
edit_window: EditWindow;
search_bar: SearchBar;
directory_view?: string;
children?: import('svelte').Snippet;
} = $props();
@@ -206,7 +204,7 @@ onMount(() => {
{#if !$nav.selecting}
<div class="toolbar">
<div class="toolbar_left">
<button onclick={() => {search_bar.open()}} title="Press / to search">
<button onclick={() => open_search()} title="Press / to search">
<i class="icon">search</i>
</button>
{@render nav_buttons()}

View File

@@ -17,20 +17,17 @@ import type { FSNavigator } from "filesystem/FSNavigator";
import FsUploadWidget from "filesystem/upload_widget/FSUploadWidget.svelte";
import EditWindow from "filesystem/edit_window/EditWindow.svelte";
import DetailsWindow from "filesystem/DetailsWindow.svelte";
import SearchBar from "filesystem/SearchBar.svelte";
let {
nav,
upload_widget,
edit_window,
details_window,
search_bar,
}: {
nav: FSNavigator
upload_widget: FsUploadWidget
edit_window: EditWindow
details_window: DetailsWindow
search_bar: SearchBar
} = $props();
let viewer: any = $state()
@@ -92,7 +89,7 @@ export const seek = (delta: number) => {
{:else if viewer_type === "dir" && $nav.base.name === ".Trash"}
<TrashBin nav={nav} root_path={$nav.path[$nav.path.length - 2].path}/>
{:else if viewer_type === "dir"}
<FileManager nav={nav} upload_widget={upload_widget} edit_window={edit_window} search_bar={search_bar}>
<FileManager nav={nav} upload_widget={upload_widget} edit_window={edit_window}>
<CustomBanner path={$nav.path}/>
</FileManager>
{:else if viewer_type === "audio"}

View File

@@ -16,6 +16,7 @@ import MenuEntry from "./MenuEntry.svelte";
import { breadcrumbs_store, toolbar_store } from "./HeaderStore";
import ProgressBar from "util/ProgressBar.svelte";
import NovaLogo, { update_favicon } from "util/NovaLogo.svelte";
import SearchBar from "filesystem/SearchBar.svelte";
// The menu swipe will be detected if it was less than this much pixels from the
// screen edge
@@ -318,6 +319,8 @@ const set_offset = (off: number) => {
</div>
<SearchBar/>
<style>
.wrap {
display: flex;

View File

@@ -1,3 +1,8 @@
<script lang="ts" module>
// Opens a page like a click on a link does. Set by the Router when it mounts
export let navigate: (href: string) => void
</script>
<script lang="ts">
import { onMount, tick, type Component } from "svelte";
import NotFound from "./NotFound.svelte";
@@ -161,6 +166,8 @@ const load_page = async (href: string, history: boolean) => {
})
}
navigate = href => load_page(href, true)
const click = (e: MouseEvent) => {
// Middle clicks, right clicks and modified clicks open the link in a new
// tab or window. That's the browser's job, not ours