aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--frontend/main.ts18
-rw-r--r--frontend/query.ts17
-rw-r--r--frontend/style.sass74
-rw-r--r--frontend/ui.ts60
4 files changed, 122 insertions, 47 deletions
diff --git a/frontend/main.ts b/frontend/main.ts
index c9cd654..a5c18e7 100644
--- a/frontend/main.ts
+++ b/frontend/main.ts
@@ -1,6 +1,6 @@
/// <reference lib="dom" />
-import { load_bangs, process_query } from "./query.ts";
-import { add_page_content } from "./ui.ts"
+import { bangs, load_bangs, process_query } from "./query.ts";
+import { add_page_content, status } from "./ui.ts"
globalThis.addEventListener("hashchange", () => process_url())
@@ -12,13 +12,21 @@ globalThis.addEventListener("load", () => {
function process_url() {
if (document.location.hash.length != 0) {
const input = document.location.hash.substring(1)
- const [default_engine, query_encoded] = input.split("#")
+ const [engine, query_encoded] = input.split("#")
if (query_encoded) {
const query = decodeURIComponent(query_encoded.replaceAll("+", " "))
- process_query(default_engine, query)
+ process_query(engine, query)
} else {
- return add_page_content(default_engine)
+ add_page_content(engine)
}
+ bangs.then(bangs => {
+ console.log("bop");
+
+ if (!bangs[engine]) {
+ status("error", "Engine does not exist")
+ window.location.hash = "#"
+ }
+ })
} else {
add_page_content()
}
diff --git a/frontend/query.ts b/frontend/query.ts
index c0cc9ea..f3c7e07 100644
--- a/frontend/query.ts
+++ b/frontend/query.ts
@@ -1,14 +1,15 @@
import { status } from "./ui.ts"
// TODO embed this information into bangs.js
-const ENGINE_NAMES: {[key:string]:string} = {
+const ENGINE_PINNED: Set<string> = new Set(["ddg", "qw", "qwl", "g"])
+const ENGINE_NAMES: { [key: string]: string } = {
"ddg": "DuckDuckGo",
"qw": "Qwant",
"qwl": "Qwant Lite",
"g": "Google",
}
-interface Bangs { [key: string]: { url: string, name: string } }
+interface Bangs { [key: string]: { url: string, name?: string, pinned?: boolean } | undefined }
export let bangs: Promise<Bangs>;
export function load_bangs() {
status("info", "Loading bangs...")
@@ -16,9 +17,15 @@ export function load_bangs() {
(async () => {
const bangs_res = await fetch("/bangs.json")
if (!bangs_res.ok) return status("error", "could not download bangs.json")
- const k: {[key:string]:string} = await bangs_res.json()
+ const k: { [key: string]: string } = await bangs_res.json()
status("info", "Bangs loaded.")
- r(Object.fromEntries(Object.entries(k).map(([key,url]) => [key, { url, name: ENGINE_NAMES[key] ?? key }])))
+ r(Object.fromEntries(Object.entries(k).map(
+ ([key, url]) => [key, {
+ url,
+ name: ENGINE_NAMES[key],
+ pinned: ENGINE_PINNED.has(key)
+ }]
+ )))
})()
})
}
@@ -38,5 +45,5 @@ export async function process_query(default_engine: string, query: string) {
}
async function search_url(engine: string, query: string) {
- return (await bangs)[engine].url.replace("{{{s}}}", encodeURIComponent(query).replaceAll("%20", "+"))
+ return (await bangs)[engine]!.url.replace("{{{s}}}", encodeURIComponent(query).replaceAll("%20", "+"))
}
diff --git a/frontend/style.sass b/frontend/style.sass
index e61799a..eeaa708 100644
--- a/frontend/style.sass
+++ b/frontend/style.sass
@@ -1,16 +1,13 @@
-$ac-dark: rgb(52, 35, 50)
+$ac-dark: rgb(29, 24, 29)
$ac-light: rgb(255, 116, 227)
body
background-color: $ac-dark
margin: 0px
-p, h1, h2, h3, h4, h5, h6, input, button
+p, h1, h2, h3, h4, h5, h6, input, button, label, li
color: white
-section.info
- margin: 5em
-
.status
background-color: black
padding: 1em
@@ -24,36 +21,61 @@ section.info
&.level-success
color: #00ff00
+section.info
+ margin: 5em
+
+section.engine-select
+ margin: 10em
+ ul
+ list-style: none
+ display: flex
+ flex-direction: row
+ flex-wrap: wrap
+ li
+ background-color: #00000040
+ border-radius: 0.5em
+ padding: 1em
+ margin: 0.5em
+ &.pinned
+ width: 30%
+ cursor: pointer
+ transition: background-color 0.1s ease-out
+ &:hover
+ background-color: #00000080
section.search
width: 100vw
height: 50vh
- display: flex;
+ display: flex
flex-direction: column
- place-content: center;
- align-items: center;
+ place-content: center
+ align-items: center
font-size: large
font-weight: 500
- input, button
- border-radius: 0.5em
- padding: 0.5em
+input, button
+ border-radius: 0.5em
+ padding: 0.5em
+
+input
+ width: 25em
+ border: 0.15em solid $ac-light
+ background-color: rgba(0, 0, 0, 0.3)
+ outline: none
+ transition: background-color 0.1s ease-out, border-color 0.1s ease-out
+ &:focus
+ background-color: rgba(0, 0, 0, 0.5)
+ border-color: lightgray !important
+
+button
+ margin-left: 1em
+ background-color: $ac-light
+ backdrop-filter: blur(5px)
+ border: 0
+ cursor: pointer
- input
- width: 25em
- border: 0.15em solid $ac-light
- background-color: rgba(0, 0, 0, 0.3)
- outline: none
- &:focus
- transition: 0.1s ease-out
- background-color: rgba(0, 0, 0, 0.5)
- border-color: lightgray !important
- button
- margin-left: 1em
- background-color: $ac-light
- backdrop-filter: blur(5px)
- border: 0
- cursor: pointer
+label
+ margin-right: 1em
diff --git a/frontend/ui.ts b/frontend/ui.ts
index 4096204..6a254c7 100644
--- a/frontend/ui.ts
+++ b/frontend/ui.ts
@@ -1,15 +1,16 @@
import { bangs, process_query } from "./query.ts";
export function add_page_content(engine?: string) {
- document.getElementById("content")?.remove()
+ //@ts-ignore HTMLCollectionOf is an iterator
+ for (const e of [...document.getElementsByTagName("section")]) e.remove()
if (engine) {
- document.body.append(create_search_bar(engine), create_search_info())
+ document.body.append(section_search(engine), section_info_search())
} else {
- document.body.append(create_start_page())
+ document.body.append(section_info_start(), section_engine_select())
}
}
-function create_search_bar(engine: string) {
+function section_search(engine: string) {
const section = document.createElement("section")
section.classList.add("search")
@@ -27,7 +28,7 @@ function create_search_bar(engine: string) {
const heading = document.createElement("h1")
heading.textContent = engine
- bangs.then(bangs => heading.textContent = bangs[engine].name)
+ bangs.then(bangs => heading.textContent = bangs[engine]?.name ?? engine)
const input = document.createElement("input")
input.type = "input"
@@ -49,7 +50,47 @@ function create_search_bar(engine: string) {
return section
}
-function create_search_info() {
+function section_engine_select() {
+ const section = document.createElement("section")
+ section.classList.add("engine-select")
+
+ const select = async (e: string) => {
+ if (!(await bangs)[e]) return status("error", `Engine ${JSON.stringify(e)} does not exist.`)
+ window.location.hash = `#${e}`
+ }
+
+ const heading = document.createElement("h2")
+ heading.textContent = "Select a search engine"
+
+ const listing = document.createElement("ul")
+ bangs.then(bangs => {
+ for (const key in bangs) if (bangs[key]!.pinned) {
+ const li = document.createElement("li")
+ li.classList.add("pinned")
+ li.textContent = bangs[key]!.name ?? key
+ li.onclick = () => select(key)
+ listing.prepend(li)
+ }
+ })
+ const other = document.createElement("li")
+ const label = document.createElement("label")
+ label.textContent = "Select other engine by bang:"
+ const input = document.createElement("input")
+ input.type = "input"
+ input.addEventListener("keydown", ev => {
+ if (ev.code == "Enter") select(input.value)
+ })
+ const submit = document.createElement("button")
+ submit.textContent = "Select"
+ submit.addEventListener("click", () => select(input.value))
+ other.append(label, input, submit)
+ listing.append(other)
+
+ section.append(heading, listing)
+ return section
+}
+
+function section_info_search() {
const section = document.createElement("section")
section.classList.add("info")
@@ -63,10 +104,9 @@ function create_search_info() {
return section
}
-
-function create_start_page() {
+function section_info_start() {
const section = document.createElement("section")
- section.id = "content"
+ section.classList.add("info")
const heading = document.createElement("h1")
heading.textContent = "Projectname"
@@ -78,8 +118,6 @@ function create_start_page() {
return section
}
-
-
let status_el: HTMLElement
export function status(level: "error" | "info" | "success", text: string) {
if (!status_el) {