Enable search on all pages
This commit is contained in:
@@ -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} />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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()}
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user