6.7 KiB
Search Engine Integration & URL Bar Dropdown
Goal
Integrate a search engine (DuckDuckGo default, user-changeable) into the URL bar. When the user types, a dropdown appears with direct links first (from history, bookmarks, and domain heuristics), followed by search engine suggestions. Selecting a direct link navigates to that URL; selecting a search suggestion goes to the search engine results page.
Architecture
flowchart TD
A[User types in URL entry] --> B[on_url_changed callback]
B --> C[Clear suggestion list store]
C --> D[db_history_search query]
C --> E[bookmarks_search query]
C --> F[domain heuristic]
D --> G[Add direct-link rows to model]
E --> G
F --> G
B --> H[Async SoupRequest to DDG ac API]
H --> I[Add search-suggestion rows to model]
G --> J[GtkEntryCompletion dropdown shows]
I --> J
J --> K{User selects a row}
K -->|direct link| L[webkit_web_view_load_uri url]
K -->|search suggestion| M[load search engine URL with query]
K -->|Enter, no selection| N{Is input a URL?}
N -->|Yes| L
N -->|No| M
Data Sources for Direct Links
- History — SQLite
historytable, searched by URL/title substring, ranked byvisit_count DESC, visited_at DESC. These are sites the user has actually visited. - Bookmarks — In-memory bookmark list, searched by URL/title substring.
- Domain heuristic — If the typed text has no spaces and no dots, offer
https://<text>.organdhttps://<text>.comas "Navigate directly" options. Handles first-time visits to known domains.
Search Engine Suggestions
DuckDuckGo autocomplete API: https://duckduckgo.com/ac/?q=<query>&type=list
Returns a JSON array: ["wikipedia", "wikipedia english", ...]
Fetched asynchronously via libsoup (already linked). Results populate the lower section of the dropdown. Selecting one navigates to https://duckduckgo.com/?q=<term>.
Search Engine Configuration
Built-in engines hardcoded in search.c:
| Engine | Search URL | Suggestion URL |
|---|---|---|
| DuckDuckGo | https://duckduckgo.com/?q=%s |
https://duckduckgo.com/ac/?q=%s&type=list |
https://www.google.com/search?q=%s |
https://suggestqueries.google.com/complete/search?client=firefox&q=%s |
|
| Brave | https://search.brave.com/search?q=%s |
https://search.brave.com/api/suggest?q=%s |
| Startpage | https://www.startpage.com/sp/search?query=%s |
(none — no autocomplete) |
| Searx | https://searx.be/search?q=%s |
(none) |
The selected engine name is stored in settings (search_engine key) and synced via NIP-78.
Files to Create
src/search.h + src/search.c
search_engine_tstruct: name, search_url_template, suggestion_url_templatesearch_engines_get()— returns array of built-in enginessearch_engine_get_active()— returns the currently selected enginesearch_engine_build_search_url(const char *query)— builds a search URL from the active engine's templatesearch_engine_build_suggestion_url(const char *query)— builds the suggestion API URLsearch_suggest_fetch_async(const char *query, GFunc callback, gpointer user_data)— async libsoup HTTP GET, parses JSON array, calls callback with resultssearch_is_url(const char *input)— heuristic: returns TRUE if input looks like a URL (has scheme, or has a dot with no spaces)
Files to Modify
src/settings.h + src/settings.c
- Add
char search_engine[64]tobrowser_settings_t(default "duckduckgo") - Load/save the
search_enginekey from db_kv
src/db.h + src/db.c
- Add
db_history_search(const char *query, char ***urls_out, char ***titles_out, int *count_out, int limit)—WHERE url LIKE '%q%' OR title LIKE '%q%' ORDER BY visit_count DESC, visited_at DESC LIMIT ? - Add index on
history(url)andhistory(title)for search performance
src/tab_manager.c
- Add a
GtkListStore(per-tab or shared) with columns: display text, URL, item type (direct/suggestion), icon name - Add
GtkEntryCompletionto each tab'surl_entrywith a custom match function - Add
on_url_changedcallback — rebuilds the list store on each keystroke:- Clear store
- Query history via
db_history_search() - Query bookmarks via
bookmarks_get_dirs()+ filter - Add domain heuristic entries if applicable
- Fire async
search_suggest_fetch_async()— on completion, append suggestion rows
- Override
match-selectedsignal — read the URL column; if it's a direct link, navigate; if it's a search suggestion, build search URL and navigate - Modify
on_url_activate— if input is not a URL (persearch_is_url()), build a search URL and navigate instead of prependinghttps:// - Modify
normalize_url— if input is not a URL and not an about: URL, treat as a search query
src/nostr_bridge.c
- Add a "Search Engine" section to the settings page HTML with a
<select>dropdown of built-in engines - Add
search_engineto thehandle_settings_setkey/value handler
src/settings_sync.c
- Add
"search_engine"tog_sync_setting_keys[]whitelist
Makefile
- Add
src/search.ctoSRC
Dropdown UX Design
Each row in the completion dropdown shows:
- Direct links (history/bookmarks/domain):
🌐 wikipedia.org — Wikipedia(URL + title), with a history/bookmark icon - Search suggestions:
🔍 wikipedia english(search term), with a search icon
Direct links always appear before search suggestions. A visual separator (different icon, possibly different text color via Pango markup) distinguishes the two categories.
Enter Key Behavior
When the user presses Enter without selecting a dropdown item:
- If
search_is_url(input)is true → navigate to the URL (current behavior) - If not → build a search URL from the active engine and navigate
This means typing "wikipedia" and pressing Enter goes to DDG search, but typing "wikipedia.org" and pressing Enter goes directly to wikipedia.org. Typing "wikipedia" and selecting the history entry for wikipedia.org from the dropdown goes directly there.
Implementation Order
- Create
src/search.h+src/search.c(engine definitions, URL builders, async suggestion fetch, URL heuristic) - Add
db_history_search()tosrc/db.h+src/db.c+ search indexes - Add
search_enginesetting tosrc/settings.h+src/settings.c - Add search engine dropdown to settings page in
src/nostr_bridge.c - Add
search_engineto sync whitelist insrc/settings_sync.c - Implement URL bar dropdown in
src/tab_manager.c(list store, entry completion, changed callback, match-selected handler) - Update
on_url_activate/normalize_urlfor search fallback - Add
src/search.ctoMakefile - Build and test