Files

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
  1. History — SQLite history table, searched by URL/title substring, ranked by visit_count DESC, visited_at DESC. These are sites the user has actually visited.
  2. Bookmarks — In-memory bookmark list, searched by URL/title substring.
  3. Domain heuristic — If the typed text has no spaces and no dots, offer https://<text>.org and https://<text>.com as "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
Google 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_t struct: name, search_url_template, suggestion_url_template
  • search_engines_get() — returns array of built-in engines
  • search_engine_get_active() — returns the currently selected engine
  • search_engine_build_search_url(const char *query) — builds a search URL from the active engine's template
  • search_engine_build_suggestion_url(const char *query) — builds the suggestion API URL
  • search_suggest_fetch_async(const char *query, GFunc callback, gpointer user_data) — async libsoup HTTP GET, parses JSON array, calls callback with results
  • search_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] to browser_settings_t (default "duckduckgo")
  • Load/save the search_engine key 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) and history(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 GtkEntryCompletion to each tab's url_entry with a custom match function
  • Add on_url_changed callback — rebuilds the list store on each keystroke:
    1. Clear store
    2. Query history via db_history_search()
    3. Query bookmarks via bookmarks_get_dirs() + filter
    4. Add domain heuristic entries if applicable
    5. Fire async search_suggest_fetch_async() — on completion, append suggestion rows
  • Override match-selected signal — 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 (per search_is_url()), build a search URL and navigate instead of prepending https://
  • 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_engine to the handle_settings_set key/value handler

src/settings_sync.c

  • Add "search_engine" to g_sync_setting_keys[] whitelist

Makefile

  • Add src/search.c to SRC

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:

  1. If search_is_url(input) is true → navigate to the URL (current behavior)
  2. 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

  1. Create src/search.h + src/search.c (engine definitions, URL builders, async suggestion fetch, URL heuristic)
  2. Add db_history_search() to src/db.h + src/db.c + search indexes
  3. Add search_engine setting to src/settings.h + src/settings.c
  4. Add search engine dropdown to settings page in src/nostr_bridge.c
  5. Add search_engine to sync whitelist in src/settings_sync.c
  6. Implement URL bar dropdown in src/tab_manager.c (list store, entry completion, changed callback, match-selected handler)
  7. Update on_url_activate / normalize_url for search fallback
  8. Add src/search.c to Makefile
  9. Build and test