import {
Badge,
createDisclosure,
HStack,
Icon,
IconButton,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
Text,
VStack,
hope,
} from "@hope-ui/solid"
import { BsSearch } from "solid-icons/bs"
import {
createSignal,
For,
Match,
onCleanup,
onMount,
Show,
Switch,
} from "solid-js"
import Mark from "mark.js"
import {
FullLoading,
LinkWithBase,
Paginator,
SelectWrapper,
} from "~/components"
import { useFetch, usePath, useRouter, useT } from "~/hooks"
import { getMainColor, me, password } from "~/store"
import { SearchNode } from "~/types"
import {
bus,
encodePath,
fsSearch,
getFileSize,
handleResp,
hoverColor,
pathJoin,
} from "~/utils"
import { isMac } from "~/utils/compatibility"
import { getIconByObj } from "~/utils/icon"
// class MarkKeywords {
// root
// rootHTML
// style
// /**
// * Keyword highlight
// * @param root Find root elements
// * @param style The default background is highly bright yellow
// */
// constructor(config: { root: Element | null; style?: string }) {
// if (!config.root) return
// this.root = config.root
// this.rootHTML = config.root.innerHTML
// this.style = config.style ?? "background-color: #FF0"
// }
// /** mark keyword */
// light(keyword: string) {
// const handler = (root: any) => {
// if (
// root.nodeName === "#text" &&
// root.parentNode.childNodes.length === 1
// ) {
// root.parentNode.innerHTML = root.parentNode.innerHTML.replace(
// new RegExp(keyword, "g"),
// `${keyword}`,
// )
// } else {
// for (const node of root.childNodes) {
// handler(node)
// }
// }
// }
// if (!this.root) return
// // reset HTML
// this.root.innerHTML = this.rootHTML!
// if (!keyword) return
// handler(this.root)
// }
// }
function NodeName(props: { keywords: string; name: string }) {
let ref: HTMLSpanElement
onMount(() => {
// const highlighter = new MarkKeywords({
// root: ref!,
// style: `background-color: var(--hope-colors-info5); border-radius: var(--hope-radii-md); margin: 0 1px; padding: 0 1px;`,
// })
// highlighter.light(props.keywords)
const mark = new Mark(ref!)
mark.mark(props.keywords, {
separateWordSearch: true,
diacritics: true,
})
})
return (
{props.name}
)
}
const SearchResult = (props: { node: SearchNode; keywords: string }) => {
const { setPathAs } = usePath()
return (
{
setPathAs(props.node.path, props.node.is_dir)
}}
>
0 || !props.node.is_dir}>
{getFileSize(props.node.size)}
{props.node.parent}
)
}
const Search = () => {
const pageSize = 100
const { isOpen, onOpen, onClose, onToggle } = createDisclosure()
const t = useT()
const handler = (name: string) => {
if (name === "search") {
onOpen()
}
}
bus.on("tool", handler)
const searchEvent = (e: KeyboardEvent) => {
if ((e.ctrlKey || (isMac && e.metaKey)) && e.key.toLowerCase() === "k") {
e.preventDefault()
onToggle()
}
}
document.addEventListener("keydown", searchEvent)
onCleanup(() => {
bus.off("tool", handler)
document.removeEventListener("keydown", searchEvent)
})
const [keywords, setKeywords] = createSignal("")
const { pathname } = useRouter()
const [loading, searchReq] = useFetch(fsSearch)
const [data, setData] = createSignal({
content: [] as SearchNode[],
total: 0,
})
const [scope, setScope] = createSignal(0)
const scopes = ["all", "folder", "file"]
let resetPaginator: () => void
const search = async (page = 1) => {
page === 1 && resetPaginator?.()
if (loading()) return
setData({
content: [],
total: 0,
})
const resp = await searchReq(
pathname(),
keywords(),
password(),
scope(),
page,
pageSize,
)
handleResp(resp, (data) => {
const content = data.content
if (!content) {
return
}
content.forEach((node) => {
if (me().base_path && node.parent.startsWith(me().base_path)) {
const pattern = new RegExp("^" + me().base_path)
node.parent = node.parent.replace(pattern, "") || "/"
if (!node.parent.startsWith("/")) {
node.parent = "/" + node.parent
}
}
node.path = encodePath(pathJoin(node.parent, node.name))
})
setData(data)
})
}
return (
{t("home.search.search")}
setScope(v)}
options={scopes.map((v, i) => ({
value: i,
label: t(`home.search.scopes.${v}`),
}))}
/>
{
setKeywords(e.currentTarget.value)
}}
onKeyDown={(e) => {
if (e.key === "Enter" && keywords().length !== 0) {
search()
}
}}
/>
}
onClick={() => search()}
loading={loading()}
disabled={keywords().length === 0}
/>
{t("home.search.no_result")}
{(item) => }
{
search(page)
}}
setResetCallback={(reset) => (resetPaginator = reset)}
/>
)
}
export { Search }