Skip to content

Commit da51b28

Browse files
authored
Merge pull request #666 from Rigelyon/update-web-search
feat(web-search): Add direct URL and IP opening functionality
2 parents dd7afea + 27cbd23 commit da51b28

8 files changed

Lines changed: 137 additions & 12 deletions

File tree

web-search/LauncherProvider.qml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Item {
2020
readonly property string engineName: cfg.search_engine ?? defaults.search_engine ?? "Google"
2121
readonly property bool showSuggestions: cfg.show_suggestions ?? defaults.show_suggestions ?? true
2222
readonly property int maxResults: cfg.max_results ?? defaults.max_results ?? 5
23+
readonly property bool directUrl: cfg.direct_url ?? defaults.direct_url ?? true
2324

2425
readonly property var engine: {
2526
if (engineName === "DuckDuckGo") {
@@ -35,6 +36,33 @@ Item {
3536
}
3637
}
3738

39+
function isUrl(text) {
40+
if (!text || text.includes(" ")) return false;
41+
42+
if (/^https?:\/\//i.test(text)) return true;
43+
44+
const localhostPattern = /^localhost(:[0-9]+)?(\/\S*)?$/i;
45+
const ipPattern = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(:[0-9]+)?(\/\S*)?$/;
46+
const domainPattern = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z]{2,})+(:[0-9]+)?(\/\S*)?$/;
47+
48+
return localhostPattern.test(text) || ipPattern.test(text) || domainPattern.test(text);
49+
}
50+
51+
function normalizeUrl(text) {
52+
text = text.trim();
53+
if (!text) return "";
54+
if (/^[a-z0-9]+:\/\//i.test(text)) return text;
55+
56+
const isLocal = /^localhost(:[0-9]+)?(\/\S*)?$/i.test(text) ||
57+
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(:[0-9]+)?(\/\S*)?$/.test(text);
58+
59+
if (isLocal) {
60+
return "http://" + text;
61+
}
62+
63+
return "https://" + text;
64+
}
65+
3866
function getResults(searchText) {
3967
let results = [];
4068
let rawText = searchText.trim();
@@ -57,6 +85,21 @@ Item {
5785
}];
5886
}
5987

88+
if (directUrl && isUrl(query)) {
89+
let url = normalizeUrl(query);
90+
results.push({
91+
"name": pluginApi?.tr("launcher.openUrl", { url: url }),
92+
"description": pluginApi?.tr("launcher.openUrlDescription"),
93+
"icon": "link",
94+
"isTablerIcon": true,
95+
"_score": isCommand ? 1000 : -4,
96+
"onActivate": function() {
97+
Qt.openUrlExternally(url);
98+
if (launcher) launcher.close();
99+
}
100+
});
101+
}
102+
60103
results.push({
61104
"name": pluginApi?.tr("launcher.search", { query: query }),
62105
"description": pluginApi?.tr("launcher.openIn", { engine: engineName }),

web-search/README.md

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,87 @@ A launcher provider plugin that allows you to quickly search the internet direct
77
- **Quick Web Searching**: Search the web instantly without opening a browser first
88
- **Live Autocomplete**: Get search suggestions from your preferred engine as you type
99
- **Multiple Search Engines**: Support for Google, DuckDuckGo, Bing, Brave, and Yandex
10+
- **Smart URL Detection**: Automatically detects URLs, IP addresses, and localhost and opens them directly in the browser
1011
- **Smart Priorities**: Web search acts as a fallback when searching for apps, or takes absolute priority when using the explicit `>web` command
1112

1213
## Usage
1314

1415
1. Open the Noctalia launcher
15-
2. Type `>web` to enter web search mode exclusively, OR just type your query directly into the launcher and scroll to the bottom to see web search fallbacks.
16-
3. Your live suggestions will populate underneath the main result
17-
4. Hit Enter to open the query in your default browser
16+
2. Type `>web` followed by your query to enter web search mode exclusively
17+
3. Or just type your query directly. Web search results appear as fallbacks below matched applications
18+
4. Live suggestions populate underneath the main result as you type
19+
5. Press Enter on any result to open it in your default browser
1820

1921
### Examples
2022

21-
```bash
22-
# Explicitly search for recipes, bypassing all local files/apps
23+
**Search with the `>web` command:**
24+
```
2325
>web chocolate cake recipe
26+
```
27+
This bypasses all local apps/files and shows only web search results. The top result will open a search for "chocolate cake recipe" in your configured engine, with autocomplete suggestions listed below.
2428

25-
# Search fallbacks (appears at bottom of launcher below matched applications)
29+
**Fallback search:**
30+
```
2631
discord
2732
```
33+
Type a query normally. If it matches an installed app, the app appears first. Web search results appear at the bottom as fallbacks, so you can still search for "discord" on the web if the app isn't what you wanted.
34+
35+
**Direct URL navigation:**
36+
```
37+
>web github.com/noctalia-dev
38+
```
39+
When Direct URL Opening is enabled, the plugin detects that `github.com/noctalia-dev` is a URL and offers to open it directly in your browser, alongside the regular search result.
40+
41+
**Open localhost or IP addresses:**
42+
```
43+
>web localhost:3000
44+
>web 192.168.1.1
45+
```
46+
Local addresses and IPs are detected as URLs and offered for direct opening. Localhost and IP addresses default to `http://`, while domain names default to `https://`.
47+
48+
## IPC Commands
49+
50+
You can control the web search plugin via the command line using the Noctalia IPC interface.
51+
52+
### Available Commands
53+
54+
| Command | Description | Example |
55+
|---|---|---|
56+
| `toggle` | Opens or closes the launcher on the current screen | `qs -c noctalia-shell ipc call plugin:web-search toggle` |
2857

2958
## Configuration
3059

31-
You can configure the plugin directly via Noctalia's Plugin API Settings:
32-
- **Search Engine**: Choose between Google, DuckDuckGo, Bing, Brave, or Yandex
33-
- **Show Search Suggestions**: Toggle whether to fetch real-time suggestions while typing
34-
- **Maximum Results**: Control how many autocomplete suggestions appear in the launcher at once (1 to 10)
60+
You can configure the plugin directly via Noctalia's Plugin Settings:
61+
62+
| Setting | Description | Default |
63+
|---|---|---|
64+
| **Search Engine** | Choose between Google, DuckDuckGo, Bing, Brave, or Yandex | Google |
65+
| **Direct URL Opening** | Automatically detect URLs and open them directly in the browser instead of searching | Enabled |
66+
| **Show Search Suggestions** | Fetch real-time autocomplete suggestions while typing | Enabled |
67+
| **Maximum Results** | Number of autocomplete suggestions shown in the launcher (1–10) | 5 |
3568

3669
## Requirements
3770

3871
- Noctalia 3.9.0 or later
39-
- Internet connection (for search suggestions)
72+
- Internet connection (for search suggestions)
73+
74+
## Changelog
75+
76+
### 1.1.0
77+
- Added Direct URL Opening. Automatically detects URLs, IP addresses, and localhost and opens them directly in the browser
78+
- Added configurable toggle for the Direct URL feature
79+
- Smart protocol handling
80+
81+
### 1.0.2
82+
- Added French translation
83+
84+
### 1.0.1
85+
- Added German translation
86+
87+
### 1.0.0
88+
- Initial release
89+
- Live autocomplete suggestions from the selected search engine
90+
- Support for Google, DuckDuckGo, Bing, Brave, and Yandex
91+
- Configurable suggestion count and toggle
92+
- Fallback results when typing normally in the launcher
93+
- English translation

web-search/Settings.qml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ColumnLayout {
1111
property var defaults: pluginApi?.manifest?.metadata?.defaultSettings || ({})
1212

1313
property string valueSearchEngine: cfg.search_engine ?? defaults.search_engine ?? "Google"
14+
property bool valueDirectUrl: cfg.direct_url ?? defaults.direct_url ?? true
1415
property bool valueShowSuggestions: cfg.show_suggestions ?? defaults.show_suggestions ?? true
1516
property int valueMaxResults: cfg.max_results ?? defaults.max_results ?? 5
1617

@@ -36,6 +37,13 @@ ColumnLayout {
3637
onSelected: key => root.valueSearchEngine = key
3738
}
3839

40+
NToggle {
41+
label: pluginApi?.tr("settings.directUrl.label")
42+
description: pluginApi?.tr("settings.directUrl.description")
43+
checked: root.valueDirectUrl
44+
onToggled: root.valueDirectUrl = checked
45+
}
46+
3947
NToggle {
4048
label: pluginApi?.tr("settings.suggestions.label")
4149
description: pluginApi?.tr("settings.suggestions.description")
@@ -92,6 +100,7 @@ ColumnLayout {
92100
}
93101

94102
pluginApi.pluginSettings.search_engine = root.valueSearchEngine;
103+
pluginApi.pluginSettings.direct_url = root.valueDirectUrl;
95104
pluginApi.pluginSettings.show_suggestions = root.valueShowSuggestions;
96105
pluginApi.pluginSettings.max_results = root.valueMaxResults;
97106
pluginApi.saveSettings();

web-search/i18n/de.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"label": "Suchmaschine",
55
"description": "Standard-Suchmaschine, die beim Suchen im Internet geöffnet wird"
66
},
7+
"directUrl": {
8+
"label": "Direkte URL-Öffnung",
9+
"description": "URLs direkt im Browser öffnen, anstatt danach zu suchen"
10+
},
711
"suggestions": {
812
"label": "Suchvorschläge anzeigen",
913
"description": "Echtzeit-Vorschläge während der Eingabe abrufen"
@@ -18,6 +22,8 @@
1822
"searchInternet": "Mit {engine} im Internet suchen",
1923
"search": "„{query}“ suchen",
2024
"openIn": "In {engine} öffnen",
25+
"openUrl": "{url} öffnen",
26+
"openUrlDescription": "URL direkt im Browser öffnen",
2127
"suggestion": "Vorschlag von {engine}",
2228
"command": {
2329
"description": "Im Internet nach etwas suchen"

web-search/i18n/en.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"label": "Search Engine",
55
"description": "Default search engine to open when searching the web"
66
},
7+
"directUrl": {
8+
"label": "Direct URL Opening",
9+
"description": "Open URLs directly in the browser instead of searching for them"
10+
},
711
"suggestions": {
812
"label": "Show Search Suggestions",
913
"description": "Fetch real-time suggestions while typing"
@@ -18,6 +22,8 @@
1822
"searchInternet": "Search internet from {engine}",
1923
"search": "Search \"{query}\"",
2024
"openIn": "Open in {engine}",
25+
"openUrl": "Open {url}",
26+
"openUrlDescription": "Open URL directly in browser",
2127
"suggestion": "Suggestion from {engine}",
2228
"command": {
2329
"description": "Search something from the internet"

web-search/i18n/fr.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"label": "Moteur de recherche",
55
"description": "Moteur de recherche par défaut à ouvrir lors de la recherche sur le Web"
66
},
7+
"directUrl": {
8+
"label": "Ouverture directe d'URL",
9+
"description": "Ouvrir les URL directement dans le navigateur au lieu de les rechercher"
10+
},
711
"suggestions": {
812
"label": "Afficher les suggestions de recherche",
913
"description": "Récupérer des suggestions en temps réel pendant la saisie"
@@ -18,6 +22,8 @@
1822
"searchInternet": "Rechercher sur Internet depuis {engine}",
1923
"search": "Rechercher \"{query}\"",
2024
"openIn": "Ouvrir dans {engine}",
25+
"openUrl": "Ouvrir {url}",
26+
"openUrlDescription": "Ouvrir l'URL directement dans le navigateur",
2127
"suggestion": "Suggestion de {engine}",
2228
"command": {
2329
"description": "Rechercher quelque chose sur Internet"

web-search/manifest.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "web-search",
33
"name": "Web Search",
4-
"version": "1.0.2",
4+
"version": "1.1.0",
55
"author": "Rigelyon",
66
"license": "MIT",
77
"description": "Search the Internet from the Launcher.",
@@ -23,6 +23,7 @@
2323
"commandPrefix": "web",
2424
"defaultSettings": {
2525
"search_engine": "Google",
26+
"direct_url": true,
2627
"show_suggestions": true,
2728
"max_results": 5
2829
}

web-search/preview.png

587 KB
Loading

0 commit comments

Comments
 (0)