diff --git a/web-launcher/README.md b/web-launcher/README.md new file mode 100644 index 0000000..8c4db6d --- /dev/null +++ b/web-launcher/README.md @@ -0,0 +1,39 @@ +# Web Launcher + +Quickly open your favorite websites from the launcher. Favicons are downloaded automatically! + +## Plugin + +| Field | Value | +| --- | --- | +| ID | `yocraft/web-launcher` | +| Entries | Launcher provider: `web-launcher` | +| Launcher Prefix | `/web` | + +## Requirements + +A browser and `xdg-utils`. + +## Usage + +Open the Noctalia launcher and type `/web` to list all configurated websites. +Continue typing to filter by name, then activate a result to launch that website in your default browser. +You can customize the list and order of websites in settings. + +## Settings + +| Setting | Type | Default | Description | +| --- | --- | --- | --- | +| `links` | `string_list` | `see below` | Websites list and order. | +| `notify` | `bool` | `true` | Toggle notification when launching website. | +| `icon_provider` | `select` | `google` | Icon download source. | + +Default links: +``` +"GitHub|https://github.com", +"GitLab|https://gitlab.com", +"Codeberg|https://codeberg.org", +"Reddit|https://reddit.com", +"YouTube|https://youtube.com", +"Gmail|https://mail.google.com", +``` diff --git a/web-launcher/launcher.luau b/web-launcher/launcher.luau new file mode 100644 index 0000000..f0a0cb6 --- /dev/null +++ b/web-launcher/launcher.luau @@ -0,0 +1,126 @@ +local function loadLinks() + local raw = noctalia.getConfig("links") + local links = {} + + if type(raw) ~= "table" then + return links + end + + for _, line in ipairs(raw) do + local name, url = line:match("^([^|]+)|(.+)$") + if name and url then + name = noctalia.string.trim(name) + url = noctalia.string.trim(url) + if url:match("^https?://") then + table.insert(links, { name = name, url = url }) + else + noctalia.log("web-launcher: skipped non-http(s) URL: " .. tostring(line)) + end + else + noctalia.log("web-launcher: skipped malformed line (expected Name|https://url): " .. tostring(line)) + end + end + + return links +end + +local links = loadLinks() + +local function extractDomain(url) + local domain = url:match("^https?://([^/]+)") + if domain then + domain = domain:gsub("^.*@", "") + end + return domain +end + +local function faviconUrl(domain) + local provider = noctalia.getConfig("icon_provider") + local encoded = noctalia.string.urlEncode(domain) + + if provider == "duckduckgo" then + return "https://icons.duckduckgo.com/ip3/" .. encoded .. ".ico" + elseif provider == "direct" then + return "https://" .. domain .. "/favicon.ico" + else + return "https://www.google.com/s2/favicons?sz=64&domain=" .. encoded + end +end + +local function faviconCachePath(domain) + local provider = noctalia.getConfig("icon_provider") + + local dir = noctalia.pluginDir() .. "/cache" + local safe = domain:gsub("[^%w%.%-]", "_") + + local path = dir .. "/" .. safe .. "_" .. provider .. ".png" + return path, dir +end + +local function downloadFavicon(domain, onDone) + local path, dir = faviconCachePath(domain) + if noctalia.fileExists(path) then + onDone(path) + return + end + + noctalia.mkdirAll(dir) + noctalia.download(faviconUrl(domain), path, function(ok) + if ok then + onDone(path) + end + end) +end + +function onQuery(query) + local text = noctalia.string.trim(query) + local results = {} + + for _, link in ipairs(links) do + local domain = extractDomain(link.url) + local iconPath = faviconCachePath(domain) + local hasIcon = noctalia.fileExists(iconPath) + + local glyphValue = hasIcon and nil or "world" + local iconValue = hasIcon and iconPath or nil + + if not hasIcon then + downloadFavicon(domain, function() end) + end + + if text == "" then + table.insert(results, { + id = link.url, + title = link.name, subtitle = link.url, + glyph = glyphValue, icon = iconValue + }) + else + local score = noctalia.fuzzyScore(text, link.name) + if score ~= nil then + table.insert(results, { + id = link.url, + title = link.name, subtitle = link.url, + glyph = glyphValue, icon = iconValue, + score = score + }) + end + end + end + + launcher.setResults(query, results) +end + +local function shellEscape(raw) + return "'" .. raw:gsub("'", "'\\''") .. "'" +end + +function onActivate(id) + noctalia.runAsync("xdg-open " .. shellEscape(id)) + + if noctalia.getConfig("notify") then + noctalia.notify( + noctalia.tr("notify.title"), + noctalia.tr("notify.message", { name = id }) + ) + end +end diff --git a/web-launcher/plugin.toml b/web-launcher/plugin.toml new file mode 100644 index 0000000..9e84541 --- /dev/null +++ b/web-launcher/plugin.toml @@ -0,0 +1,51 @@ +id = "yocraft/web-launcher" +name = "Web Launcher" +version = "1.0.0" +plugin_api = 3 +author = "yocraft" +license = "MIT" +deprecated = false +icon = "world" +description = "Quickly open your favorite websites from the launcher." +tags = ["launcher", "utility", "network", "productivity"] +dependencies = [ "xdg-utils" ] + +[[launcher_provider]] +id = "web-launcher" +entry = "launcher.luau" +prefix = "web" +glyph = "world" +include_in_global_search = false + +[[setting]] +key = "links" +type = "string_list" +label_key = "settings.links.label" +description_key = "settings.links.description" +default = [ + "GitHub|https://github.com", + "GitLab|https://gitlab.com", + "Codeberg|https://codeberg.org", + "Reddit|https://reddit.com", + "YouTube|https://youtube.com", + "Gmail|https://mail.google.com", +] + +[[setting]] +key = "notify" +type = "bool" +label_key = "settings.notify.label" +description_key = "settings.notify.description" +default = true + +[[setting]] +key = "icon_provider" +type = "select" +label_key = "settings.icon_provider.label" +description_key = "settings.icon_provider.description" +default = "google" +options = [ + { value = "google", label_key = "settings.icon_provider.google" }, + { value = "duckduckgo", label_key = "settings.icon_provider.duckduckgo" }, + { value = "direct", label_key = "settings.icon_provider.direct" }, +] diff --git a/web-launcher/thumbnail.webp b/web-launcher/thumbnail.webp new file mode 100644 index 0000000..9e31625 Binary files /dev/null and b/web-launcher/thumbnail.webp differ diff --git a/web-launcher/translations/en.json b/web-launcher/translations/en.json new file mode 100644 index 0000000..c3ce951 --- /dev/null +++ b/web-launcher/translations/en.json @@ -0,0 +1,23 @@ +{ + "settings": { + "links": { + "label": "Links", + "description": "Format: Name|https://url" + }, + "notify": { + "label": "Notify", + "description": "Notify when opening link." + }, + "icon_provider": { + "label": "Icon Provider", + "description": "Icon download source.", + "google": "Google", + "duckduckgo": "DuckDuckGo", + "direct": "Site's own favicon.ico" + } + }, + "notify": { + "title": "Websites", + "message": "Opening {name}" + } +}