diff --git a/screen-toolkit/README.md b/screen-toolkit/README.md index 2a20178..d6ae004 100644 --- a/screen-toolkit/README.md +++ b/screen-toolkit/README.md @@ -16,7 +16,7 @@ not the original implementation. | Field | Value | | --- | --- | | ID | `alexander/screen-toolkit` | -| Entries | Bar widget: `widget`; control-center shortcut: `toggle`; panels: `panel` (compact tools), `panel-full` (full tools), `panel-legacy` (legacy layout), `result` (result view); service: `service` | +| Entries | Bar widget: `widget`; control-center shortcut: `toggle`; panels: `panel` (standard tools), `panel-legacy` (legacy layout), `result` (result view); service: `service` | ## Requirements @@ -61,11 +61,10 @@ Settings → Control Center shortcuts. Left-click either one opens the main pane (or stops a recording); right-clicking the bar widget quick-picks a color. While a recording is active, the widget and shortcut show a pulsing red dot. -The main panel has three layouts, selected by the `panel-mode` setting (default: -**Full**): +The main panel has two layouts, selected by the `panel-mode` setting (default: +**Standard**): -- **Full** — the spacious original grid with section titles (`panel-full`, 660×340). -- **Compact** — a dense grid grouped into tinted sections (`panel`, 380×290). +- **Standard** — a dense grid grouped into tinted sections (`panel`, 380×260). - **Legacy** — recreates the Noctalia-v4 layout (`panel-legacy`, 380×260). ### Legacy mode @@ -77,11 +76,10 @@ Legacy mode recreates the original Noctalia v4 screen-toolkit layout: - Preview and one-click access to the most recent screenshot or recording. - Quick microphone and system audio toggles in the `Record` subpanel. -The widget and shortcut open whichever entry matches the setting; the panel -footnote under Settings → Plugins shows all three panels' placement/position -options. +The widget and shortcut open the panel matching the `panel-mode` setting; the +panel footnote under Settings → Plugins shows placement/position options. -Toggle the tools panel (opens the entry matching the `panel-mode` setting): +Toggle the tools panel (opens the panel matching `panel-mode`): ```sh noctalia msg plugin alexander/screen-toolkit:service all toggle @@ -93,20 +91,12 @@ For example, bind it to `SUPER+P` in Hyprland: bind = SUPER, P, exec, noctalia msg plugin alexander/screen-toolkit:service all toggle ``` -Because `toggle` reads the `panel-mode` setting, this single bind works in all three layouts (Full, Compact and Legacy), so there is no need to change the keybind when you switch layouts. - -Open the compact tools panel: +Open the standard tools panel: ```sh noctalia msg panel-toggle alexander/screen-toolkit:panel ``` -Open the full tools panel (the original spacious grid): - -```sh -noctalia msg panel-toggle alexander/screen-toolkit:panel-full -``` - Open the legacy tools panel (the 4×2 grid with subpanels): ```sh @@ -178,7 +168,7 @@ All settings live in Settings → Plugins (gear on the plugin's row). | `record-skip-confirmation` | `bool` | `false` | Save automatically when a recording ends, skipping the save dialog. | | `record-copy-to-clipboard` | `bool` | `false` | Finalize to MP4 and copy the file URI when recording ends. | | `gif-max-seconds` | `int` | `30` | Cap for GIF recordings (1–600 s). | -| `panel-mode` | `select` | `full` | Main panel layout: `full` (spacious original grid, 660×340) or `compact` (dense grid, 380×290) or `legacy` (4×2 legacy grid, 380×260). | +| `panel-mode` | `select` | `standard` | Main panel layout: `standard` (dense grid, 380×260) or `legacy` (4×2 legacy grid, 380×260). | ## IPC @@ -208,9 +198,8 @@ noctalia msg plugin alexander/screen-toolkit:service all clearResult noctalia msg plugin alexander/screen-toolkit:service all clearHistory ``` -`toggle` opens the tools panel **matching the `panel-mode` setting** — one IPC -that works for all three layouts. The bar widget and control-center shortcut use the -same mode-aware toggle. +`toggle` opens the panel matching the `panel-mode` setting. The bar widget and +control-center shortcut use the same logic. Commands that take a payload: @@ -231,7 +220,7 @@ Summary of every service command: | Command | Payload | Action | | --- | --- | --- | -| `toggle` | — | Open/close the tools panel that matches `panel-mode` | +| `toggle` | — | Open/close the tools panel (matches `panel-mode`) | | `colorPicker` | — | Pick a color from the screen (region crosshair) | | `ocr` | — | Extract text from a region | | `qr` | — | Decode a QR / barcode from a region | @@ -258,13 +247,13 @@ Summary of every service command: ## Notes -- **Three panel entries, one layout setting.** Panel size is host-owned: the host +- **Two panel entries, one layout setting.** Panel size is host-owned: the host sizes each `[[panel]]` entry from its `width`/`height`, and there is no runtime - resize. So the three layouts are three entries sharing `panel.luau`: `panel-full` - (660×340, the original spacious grid), `panel` (380×290, the compact grid) and `panel-legacy` (380×260, the legacy grid). - The `panel-mode` setting picks which one renders, and `toggle`/widget/shortcut - all open the matching entry. Changing the setting only affects which panel - opens next time; an already-open panel keeps its current size until closed. + resize. So the two layouts are two entries sharing `panel.luau`: + `panel` (380×260, the standard grid) and `panel-legacy` (380×260, the legacy grid). + The `panel-mode` setting picks which one `toggle` opens; changing the setting + only affects which panel opens next time; an already-open panel keeps its + current size until closed. - This is a port of the legacy v4 [screen-toolkit](https://github.com/noctalia-dev/legacy-v4-plugins/tree/main/screen-toolkit) plugin. Tools that relied on freeform v4 QML overlays are adapted: region diff --git a/screen-toolkit/panel.luau b/screen-toolkit/panel.luau index 008da50..4185423 100644 --- a/screen-toolkit/panel.luau +++ b/screen-toolkit/panel.luau @@ -3,8 +3,8 @@ -- -- Thin client for the toolkit. Two layouts are provided, selected by the -- "panel-mode" plugin setting: --- * compact — a dense grid grouped into tinted sections (default) --- * full — the original spacious layout with section titles +-- * standard — the default dense grid grouped into tinted sections +-- * legacy — recreates the Noctalia-v4 layout -- The panel entry to open (and thus its host-owned size) is chosen by the -- bar [[widget]] / control-center [[shortcut]] from the same setting. -- It only dispatches actions to the [[service]] through the "command" @@ -43,8 +43,8 @@ end local function getMode() local mode = noctalia.getConfig("panel-mode") - if mode == "full" or mode == "compact" or mode == "legacy" then return mode end - return "full" + if mode == "standard" or mode == "legacy" then return mode end + return "standard" end -- Capture tools must not see the panel in the frame, so close it first. @@ -78,7 +78,7 @@ end -- ── Tool data ────────────────────────────────────────────────────────────── --- For Compact-mode and Full-mode layouts +-- For Compact-mode layout local TOOLS = { { action = "colorPicker", label_key = "tools.colorpicker", glyph = "palette" }, { action = "ocr", label_key = "tools.ocr", glyph = "scan" }, @@ -117,7 +117,7 @@ local TOOLS_LEGACY = { local function getActiveItems() local mode = getMode() - if mode == "compact" or mode == "full" then + if mode == "standard" then local list = {} for _, t in ipairs(TOOLS) do table.insert(list, { type = "tool", action = t.action }) end for _, t in ipairs(ANNOTATE_TOOLS) do table.insert(list, { type = "tool", action = t.action }) end @@ -198,7 +198,7 @@ local function headerActions(includeClose) end if includeClose then table.insert(actions, ui.button({ - key = "header-close-btn", glyph = "close", onClick = function() panel.close() end, + key = "header-close-btn", glyph = "close", width = 24, height = 24, glyphSize = 12, onClick = function() panel.close() end, })) end return ui.row({ gap = 4 }, actions) @@ -206,7 +206,7 @@ end -- ── Compact mode ─────────────────────────────────────────────────────────── -local function compactHeader() +local function standardHeader() return ui.row({ align = "center", gap = 6 }, { ui.glyph({ name = "crosshair", size = 16, color = "primary" }), ui.label({ text = tr("panel.title"), flexGrow = 1, fontSize = 16, fontWeight = "bold", color = "on_surface" }), @@ -227,78 +227,33 @@ local function setHoveredTool(action) updateFocusedTool() end -local function compactTile(t) +local function standardTile(t) local isFocused = (hoveredTool == t.action) or (focusedTool == t.action) local color = isFocused and "primary" or "on_surface" + local hoverFn = function(state) setHoveredTool((state == "true") and t.action or nil); render() end + local clickFn = function() runTool(t.action) end return ui.column({ key = "tile-" .. t.action, flexGrow = 1, gap = 2, align = "center", paddingV = 4, radius = 8, - fill = isFocused and "primary/0.15" or "surface_variant", border = isFocused and "primary" or "surface_variant", borderWidth = isFocused and 1 or 0, - onClick = function() runTool(t.action) end, - onHover = function(state) setHoveredTool((state == "true") and t.action or nil); render() end, }, { - ui.column({ width = 30, height = 30, radius = 9, fill = isFocused and "primary/0.2" or "on_primary", border = isFocused and "primary" or "on_primary", borderWidth = 1, align = "center", justify = "center" }, { + ui.column({ width = 30, height = 30, radius = 9, fill = isFocused and "primary/0.2" or "on_primary", border = isFocused and "primary" or "on_primary", borderWidth = 1, align = "center", justify = "center", onClick = clickFn, onHover = hoverFn }, { ui.glyph({ name = t.glyph, size = 16, color = color }), }), - ui.label({ text = tr(t.label_key), maxWidth = 100, maxLines = 1, textAlign = "center", fontSize = 11, color = color }), + ui.label({ text = tr(t.label_key), maxWidth = 100, maxLines = 1, textAlign = "center", fontSize = 11, color = color, onClick = clickFn, onHover = hoverFn }), }) end -local function compactToolsRow(tools) +local function standardToolsRow(tools) local row = {} - for _, t in ipairs(tools) do row[#row + 1] = compactTile(t) end + for _, t in ipairs(tools) do row[#row + 1] = standardTile(t) end return ui.row({ flexGrow = 1, gap = 2 }, row) end -local function compactSection(tools) - return ui.column({ gap = 4, paddingV = 8, paddingH = 6, radius = 12, fill = "surface_variant" }, { compactToolsRow(tools) }) +local function standardSection(tools) + return ui.column({ gap = 4, paddingV = 4, paddingH = 6, radius = 12, fill = "surface_variant" }, { standardToolsRow(tools) }) end -local function compactGrid() - return ui.column({ gap = 6 }, { compactSection(TOOLS), compactSection(ANNOTATE_TOOLS), compactSection(RECORD_TOOLS) }) -end - --- ── Full mode ────────────────────────────────────────────────────────────── - -local function fullHeader() - return ui.row({ align = "center", gap = 10 }, { - ui.glyph({ name = "crosshair", size = 24, color = "primary" }), - ui.label({ text = tr("panel.title"), flexGrow = 1, fontSize = 22, fontWeight = "bold", color = "on_surface" }), - headerActions(true), - }) -end - -local function fullTile(t) - local isFocused = (hoveredTool == t.action) or (focusedTool == t.action) - local color = isFocused and "primary" or "on_surface" - return ui.column({ - key = "tile-" .. t.action, flexGrow = 1, gap = 6, align = "center", paddingV = 6, radius = 12, - fill = "surface_variant", borderWidth = 1, border = color == "primary" and "primary" or "outline", - onClick = function() runTool(t.action) end, - onHover = function(state) setHoveredTool((state == "true") and t.action or nil); render() end, - }, { - ui.column({ width = 30, height = 30, radius = 9, fill = "on_primary", border = color == "primary" and "primary" or "on_primary", borderWidth = 1, align = "center", justify = "center" }, { - ui.glyph({ name = t.glyph, size = 16, color = color }), - }), - ui.label({ text = tr(t.label_key), maxWidth = 100, maxLines = 1, textAlign = "center", fontSize = 11, color = color }), - }) -end - -local function fullToolsRow(tools) - local row = {} - for _, t in ipairs(tools) do row[#row + 1] = fullTile(t) end - return ui.row({ flexGrow = 1, gap = 6 }, row) -end - -local function sectionLabel(text) - return ui.label({ text = text, fontSize = 11, fontWeight = "bold", color = "on_surface_variant" }) -end - -local function fullGrid() - return ui.column({ flexGrow = 1, gap = 4, justify = "space_between" }, { - sectionLabel(tr("panel.section_capture")), fullToolsRow(TOOLS), - sectionLabel(tr("panel.section_annotate")), fullToolsRow(ANNOTATE_TOOLS), - sectionLabel(tr("panel.section_record")), fullToolsRow(RECORD_TOOLS), - }) +local function standardGrid() + return ui.column({ gap = 6 }, { standardSection(TOOLS), standardSection(ANNOTATE_TOOLS), standardSection(RECORD_TOOLS) }) end -- ── Legacy mode ──────────────────────────────────────────────────────────── @@ -489,7 +444,7 @@ function onKey(chord, pressed) elseif key == "down" then if mode == "legacy" and activeView == "main" then focusedIndex = focusedIndex <= 4 and (focusedIndex + 4) or (focusedIndex - 4) - elseif mode == "compact" or mode == "full" then + elseif mode == "standard" then focusedIndex = (focusedIndex <= 6 and math.min(7 + math.floor((focusedIndex - 1) / 2), 9)) or (focusedIndex <= 9 and (10 + (focusedIndex - 7)) or ((focusedIndex - 10) + 1)) else focusedIndex = (focusedIndex % #items) + 1 @@ -497,7 +452,7 @@ function onKey(chord, pressed) elseif key == "up" then if mode == "legacy" and activeView == "main" then focusedIndex = focusedIndex > 4 and (focusedIndex - 4) or (focusedIndex + 4) - elseif mode == "compact" or mode == "full" then + elseif mode == "standard" then focusedIndex = (focusedIndex >= 10 and math.min(7 + (focusedIndex - 10), 9)) or (focusedIndex >= 7 and ((focusedIndex - 7) * 2 + 1) or math.min(10 + math.floor((focusedIndex - 1) / 2), 13)) else focusedIndex = (focusedIndex - 2) % #items + 1 @@ -527,8 +482,7 @@ end render = function() updateFocusedTool() local mode = getMode() - local body = (mode == "full" and ui.column({ flexGrow = 1, gap = 10 }, { fullHeader(), fullGrid() })) - or (mode == "compact" and ui.column({ flexGrow = 1, gap = 6 }, { compactHeader(), compactGrid() })) + local body = (mode == "standard" and ui.column({ flexGrow = 1, gap = 6 }, { standardHeader(), standardGrid() })) or (activeView == "annotate" and MarkupSubpanel()) or (activeView == "record" and RecordSubpanel()) or ui.column({ flexGrow = 1, gap = 6 }, { legacyHeader(), legacyGrid() }) diff --git a/screen-toolkit/plugin.toml b/screen-toolkit/plugin.toml index 6506cf1..96e071b 100644 --- a/screen-toolkit/plugin.toml +++ b/screen-toolkit/plugin.toml @@ -8,7 +8,7 @@ id = "alexander/screen-toolkit" name = "Screen Toolkit" -version = "1.2.0" +version = "1.2.1" plugin_api = 13 author = "alexander" license = "MIT" @@ -45,24 +45,13 @@ dependencies = [ # Main toolkit panel: tool grid + per-tool result views + recording controls. # Open with: noctalia msg panel-toggle alexander/screen-toolkit:panel -# Compact layout (default). Full mode uses the "panel-full" entry below; the -# bar widget / shortcut open whichever entry matches the "panel-mode" setting. +# Compact layout (default). Full mode was removed; the bar widget / shortcut +# open either the standard or legacy entry based on the "panel-mode" setting. [[panel]] id = "panel" entry = "panel.luau" width = 380 -height = 290 -placement = "floating" -position = "center" -keyboard_focus = "on_demand" -capture_keys = ["Tab", "Backtab", "Shift+Tab", "Up", "Down", "Left", "Right", "Return", "Enter", "Space", "Escape"] - -# Full-mode layout: the original spacious grid (660x340). -[[panel]] -id = "panel-full" -entry = "panel.luau" -width = 660 -height = 340 +height = 260 placement = "floating" position = "center" keyboard_focus = "on_demand" @@ -223,10 +212,9 @@ key = "panel-mode" type = "select" label_key = "settings.panel_mode.label" description_key = "settings.panel_mode.description" -default = "full" +default = "standard" options = [ - { value = "compact", label_key = "settings.panel_mode.options.compact" }, - { value = "full", label_key = "settings.panel_mode.options.full" }, + { value = "standard", label_key = "settings.panel_mode.options.standard" }, { value = "legacy", label_key = "settings.panel_mode.options.legacy" }, ] diff --git a/screen-toolkit/service.luau b/screen-toolkit/service.luau index ff9da16..c8ff75a 100644 --- a/screen-toolkit/service.luau +++ b/screen-toolkit/service.luau @@ -16,7 +16,6 @@ -- lands in /tmp as MP4; GIF is produced on save via record.sh convert-gif. local PANEL_ID = "alexander/screen-toolkit:panel" -local FULL_PANEL_ID = "alexander/screen-toolkit:panel-full" local LEGACY_PANEL_ID = "alexander/screen-toolkit:panel-legacy" local RESULT_PANEL_ID = "alexander/screen-toolkit:result" @@ -937,7 +936,7 @@ local HANDLERS = { setAudioIn = function(payload) overrideAudioIn = (type(payload) == "table" and payload.value or payload) == true end, toggle = function() local mode = cfg("panel-mode") - local id = mode == "full" and FULL_PANEL_ID or (mode == "legacy" and LEGACY_PANEL_ID or PANEL_ID) + local id = mode == "legacy" and LEGACY_PANEL_ID or PANEL_ID noctalia.togglePanel(id) end, } diff --git a/screen-toolkit/shortcut.luau b/screen-toolkit/shortcut.luau index a2236b0..fbbf906 100644 --- a/screen-toolkit/shortcut.luau +++ b/screen-toolkit/shortcut.luau @@ -22,8 +22,8 @@ function onClick() -- The shortcut tile never stops a recording; it just opens the panel so -- the stop button (in the panel header, next to the close X) is reachable. local mode = noctalia.getConfig("panel-mode") - local panelId = mode == "full" and "alexander/screen-toolkit:panel-full" or (mode == "legacy" and "alexander/screen-toolkit:panel-legacy" or "alexander/screen-toolkit:panel") - noctalia.togglePanel(panelId) + local id = (mode == "legacy") and "alexander/screen-toolkit:panel-legacy" or "alexander/screen-toolkit:panel" + noctalia.togglePanel(id) end apply() diff --git a/screen-toolkit/thumbnail.webp b/screen-toolkit/thumbnail.webp index b96141e..c44915f 100644 Binary files a/screen-toolkit/thumbnail.webp and b/screen-toolkit/thumbnail.webp differ diff --git a/screen-toolkit/translations/en.json b/screen-toolkit/translations/en.json index 32e271c..f60f8ef 100644 --- a/screen-toolkit/translations/en.json +++ b/screen-toolkit/translations/en.json @@ -98,11 +98,10 @@ "label": "Hide Cursor in Recordings" }, "panel_mode": { - "description": "Layout of the main panel. Compact is the dense grid; Full is the original spacious grid.", + "description": "Layout of the main panel. Standard is the default dense grid; Legacy recreates the Noctalia-v4 layout.", "label": "Panel Mode", "options": { - "compact": "Compact", - "full": "Full", + "standard": "Standard", "legacy": "Legacy" } }, diff --git a/screen-toolkit/widget.luau b/screen-toolkit/widget.luau index ceffe2d..eec9674 100644 --- a/screen-toolkit/widget.luau +++ b/screen-toolkit/widget.luau @@ -56,8 +56,8 @@ function onClick() -- The bar icon never stops a recording; it just opens the panel so the -- stop button (in the panel header, next to the close X) is reachable. local mode = noctalia.getConfig("panel-mode") - local panelId = mode == "full" and "alexander/screen-toolkit:panel-full" or (mode == "legacy" and "alexander/screen-toolkit:panel-legacy" or "alexander/screen-toolkit:panel") - noctalia.togglePanel(panelId) + local id = (mode == "legacy") and "alexander/screen-toolkit:panel-legacy" or "alexander/screen-toolkit:panel" + noctalia.togglePanel(id) end function onRightClick()