From a0ae83d24e9e789d7827834802c8a77192662432 Mon Sep 17 00:00:00 2001 From: moons Date: Wed, 5 Aug 2026 04:37:32 +0900 Subject: [PATCH] feat --- modules/applications/labwc/home.nix | 2 +- modules/applications/nani/home/nixos.nix | 75 ++++++++++++++++++- modules/applications/niri/home/nixos.nix | 18 +---- .../patches/taskbar-overview-hook.patch | 43 +++++++++++ .../patches/window-switcher-labwc.patch | 53 ------------- modules/applications/normcap/home/nixos.nix | 44 ----------- modules/applications/normcap/meta.nix | 7 -- .../profiles/interface/linux-desktop/meta.nix | 2 +- 8 files changed, 120 insertions(+), 124 deletions(-) create mode 100644 modules/applications/noctalia/patches/taskbar-overview-hook.patch delete mode 100644 modules/applications/normcap/home/nixos.nix delete mode 100644 modules/applications/normcap/meta.nix diff --git a/modules/applications/labwc/home.nix b/modules/applications/labwc/home.nix index db470ef..57cdb05 100644 --- a/modules/applications/labwc/home.nix +++ b/modules/applications/labwc/home.nix @@ -125,7 +125,7 @@ in (execute "W-l" "loginctl lock-session") (execute "W-v" "vicinae vicinae://launch/clipboard/history?toggle=true") (execute "W-j" "nani-translate-primary") - (execute "W-S-j" "normcap-translate") + (execute "W-S-j" "nani-translate-ocr") (execute "W-C-j" "${lib.getExe' pkgs.xdg-utils "xdg-open"} naniapp://translate") (execute "W-space" "ghostty +toggle-quick-terminal") (execute "W-p" "wdisplays") diff --git a/modules/applications/nani/home/nixos.nix b/modules/applications/nani/home/nixos.nix index c5a6e7b..9d2a26f 100644 --- a/modules/applications/nani/home/nixos.nix +++ b/modules/applications/nani/home/nixos.nix @@ -1,5 +1,78 @@ -_: { +{ pkgs, ... }: +let + tessdataBest = pkgs.runCommand "tessdata-best-jpn-eng-chi-sim" { } '' + mkdir -p "$out" + ln -s ${ + pkgs.fetchurl { + url = "https://github.com/tesseract-ocr/tessdata_best/raw/main/jpn.traineddata"; + hash = "sha256-Nr35rII/WRHmJMMNBVPokLirx8MaZbPvFNqUNljEC3k="; + } + } "$out/jpn.traineddata" + ln -s ${ + pkgs.fetchurl { + url = "https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata"; + hash = "sha256-goCu0Hgv4nJXpo6hD+fvMkyg+Nhb0v0UXRwrVgvLZro="; + } + } "$out/eng.traineddata" + ln -s ${ + pkgs.fetchurl { + url = "https://github.com/tesseract-ocr/tessdata_best/raw/main/chi_sim.traineddata"; + hash = "sha256-T+8tEwbI6HYW1NPkxsZ/r11EvjNCKQz48vD246p+c1s="; + } + } "$out/chi_sim.traineddata" + ''; + + tesseract = pkgs.tesseract5.override { + tessdata = tessdataBest; + }; + + naniTranslatePrimary = pkgs.writeShellApplication { + name = "nani-translate-primary"; + + runtimeInputs = with pkgs; [ + jq + wl-clipboard + xdg-utils + ]; + + text = '' + selected_text="$(wl-paste --primary --no-newline)" || exit 0 + [ -n "$selected_text" ] || exit 0 + encoded_text="$(printf '%s' "$selected_text" | jq -sRr @uri)" + exec xdg-open "naniapp://translate?source=$encoded_text" + ''; + }; + + naniTranslateOcr = pkgs.writeShellApplication { + name = "nani-translate-ocr"; + + runtimeInputs = with pkgs; [ + grim + jq + slurp + tesseract + xdg-utils + ]; + + text = '' + geometry="$(slurp)" || exit 0 + captured_text="$( + grim -g "$geometry" - \ + | tesseract stdin stdout -l jpn+eng+chi_sim --oem 1 --psm 6 + )" + [ -n "$captured_text" ] || exit 0 + encoded_text="$(printf '%s' "$captured_text" | jq -sRr @uri)" + exec xdg-open "naniapp://translate?source=$encoded_text" + ''; + }; +in +{ programs.naniTranslateLinux.enable = true; xdg.mimeApps.defaultApplications."x-scheme-handler/naniapp" = "nani.desktop"; + + home.packages = [ + naniTranslatePrimary + naniTranslateOcr + ]; } diff --git a/modules/applications/niri/home/nixos.nix b/modules/applications/niri/home/nixos.nix index 80d836b..eea8290 100644 --- a/modules/applications/niri/home/nixos.nix +++ b/modules/applications/niri/home/nixos.nix @@ -1,24 +1,8 @@ { lib, pkgs, ... }: let keybindings = import ./keybindings.nix; - naniTranslatePrimary = pkgs.writeShellApplication { - name = "nani-translate-primary"; - runtimeInputs = with pkgs; [ - jq - wl-clipboard - xdg-utils - ]; - text = '' - selected_text="$(wl-paste --primary --no-newline)" || exit 0 - [ -n "$selected_text" ] || exit 0 - encoded_text="$(printf '%s' "$selected_text" | jq -sRr @uri)" - exec xdg-open "naniapp://translate?source=$encoded_text" - ''; - }; in { - home.packages = [ naniTranslatePrimary ]; - programs.niri.settings = { binds = keybindings // { @@ -119,7 +103,7 @@ in }; "Mod+Shift+J" = { repeat = false; - action.spawn = [ "normcap-translate" ]; + action.spawn = [ "nani-translate-ocr" ]; hotkey-overlay.title = "OCR and Translate with Nani"; }; "Mod+Ctrl+J" = { diff --git a/modules/applications/noctalia/patches/taskbar-overview-hook.patch b/modules/applications/noctalia/patches/taskbar-overview-hook.patch new file mode 100644 index 0000000..7624cc6 --- /dev/null +++ b/modules/applications/noctalia/patches/taskbar-overview-hook.patch @@ -0,0 +1,43 @@ +diff --git a/src/shell/bar/widgets/taskbar_widget.cpp b/src/shell/bar/widgets/taskbar_widget.cpp +--- a/src/shell/bar/widgets/taskbar_widget.cpp ++++ b/src/shell/bar/widgets/taskbar_widget.cpp +@@ -5,6 +5,7 @@ + #include "compositors/workspace_backend.h" + #include "config/config_service.h" + #include "core/deferred_call.h" ++#include "core/process/process.h" + #include "i18n/i18n.h" + #include "render/core/color.h" + #include "render/core/renderer.h" +@@ -36,6 +37,18 @@ + + namespace { + ++ [[nodiscard]] bool launchTaskbarOverview(const std::string& appId) { ++ constexpr const char* command = "noctalia-taskbar-overview"; ++ if (appId.empty() || !process::commandExists(command)) { ++ return false; ++ } ++ return process::runAsync({ ++ command, ++ "--app-id", ++ appId.c_str(), ++ }); ++ } ++ + // Integer centering; optional odd spare pixel on the end side (right/bottom). + [[nodiscard]] float centeredOffset(float extent, float content, float inset = 0.0F, bool oddSpareOnEnd = true) { + const float inner = std::max(0.0F, extent - inset * 2.0F); +@@ -373,6 +386,12 @@ void TaskbarWidget::activateOrLaunchPinned(const TaskModel& task) { + return; + } + ++ const std::string overviewAppId = ++ !task.appId.empty() ? task.appId : (!task.desktopEntryId.empty() ? task.desktopEntryId : task.idLower); ++ if (launchTaskbarOverview(overviewAppId)) { ++ return; ++ } ++ + const std::string cycleKey = !task.desktopEntryId.empty() ? task.desktopEntryId : task.idLower; + std::size_t& cursor = m_groupedAppCycleCursor[cycleKey]; + if (cursor >= windows.size()) { diff --git a/modules/applications/noctalia/patches/window-switcher-labwc.patch b/modules/applications/noctalia/patches/window-switcher-labwc.patch index 3dc72ab..5eefdcc 100644 --- a/modules/applications/noctalia/patches/window-switcher-labwc.patch +++ b/modules/applications/noctalia/patches/window-switcher-labwc.patch @@ -24,56 +24,3 @@ diff --git a/src/shell/switcher/window_switcher.cpp b/src/shell/switcher/window_ if (key.empty()) { continue; } -diff --git a/src/shell/bar/widgets/taskbar_widget.cpp b/src/shell/bar/widgets/taskbar_widget.cpp ---- a/src/shell/bar/widgets/taskbar_widget.cpp -+++ b/src/shell/bar/widgets/taskbar_widget.cpp -@@ -5,6 +5,7 @@ - #include "compositors/workspace_backend.h" - #include "config/config_service.h" - #include "core/deferred_call.h" -+#include "core/process/process.h" - #include "i18n/i18n.h" - #include "render/core/color.h" - #include "render/core/renderer.h" -@@ -36,6 +37,18 @@ - - namespace { - -+ [[nodiscard]] bool launchTaskbarOverview(const std::string& appId) { -+ constexpr const char* command = "noctalia-taskbar-overview"; -+ if (appId.empty() || !process::commandExists(command)) { -+ return false; -+ } -+ return process::runAsync({ -+ command, -+ "--app-id", -+ appId.c_str(), -+ }); -+ } -+ - // Integer centering; optional odd spare pixel on the end side (right/bottom). - [[nodiscard]] float centeredOffset(float extent, float content, float inset = 0.0F, bool oddSpareOnEnd = true) { - const float inner = std::max(0.0F, extent - inset * 2.0F); -@@ -373,6 +386,12 @@ void TaskbarWidget::activateOrLaunchPinned(const TaskModel& task) { - return; - } - -+ const std::string overviewAppId = -+ !task.appId.empty() ? task.appId : (!task.desktopEntryId.empty() ? task.desktopEntryId : task.idLower); -+ if (launchTaskbarOverview(overviewAppId)) { -+ return; -+ } -+ - const std::string cycleKey = !task.desktopEntryId.empty() ? task.desktopEntryId : task.idLower; - std::size_t& cursor = m_groupedAppCycleCursor[cycleKey]; - if (cursor >= windows.size()) { -@@ -792,6 +811,9 @@ void TaskbarWidget::create() { - } - if (data.button == BTN_LEFT) { - if (!cycleCandidates.empty()) { -+ if (cycleCandidates.size() > 1 && launchTaskbarOverview(current->appId)) { -+ return; -+ } - std::size_t& cursor = m_groupedAppCycleCursor[cycleKey]; - if (cursor >= cycleCandidates.size()) { - cursor = 0; diff --git a/modules/applications/normcap/home/nixos.nix b/modules/applications/normcap/home/nixos.nix deleted file mode 100644 index b8dd862..0000000 --- a/modules/applications/normcap/home/nixos.nix +++ /dev/null @@ -1,44 +0,0 @@ -{ pkgs, ... }: -let - normcap = pkgs.normcap.override { - tesseract4 = pkgs.tesseract4.override { - enableLanguages = [ - "chi_sim" - "jpn" - "eng" - ]; - }; - }; - - normcapTranslate = pkgs.writeShellApplication { - name = "normcap-translate"; - - runtimeInputs = [ - normcap - pkgs.jq - pkgs.xdg-utils - ]; - - text = '' - captured_text="$( - normcap \ - --cli-mode \ - --screenshot-handler grim \ - --show-introduction False \ - --update False \ - --detect-codes False \ - --notification False \ - -l jpn eng chi_sim - )" || exit 0 - [ -n "$captured_text" ] || exit 0 - encoded_text="$(printf '%s' "$captured_text" | jq -sRr @uri)" - exec xdg-open "naniapp://translate?source=$encoded_text" - ''; - }; -in -{ - home.packages = [ - normcap - normcapTranslate - ]; -} diff --git a/modules/applications/normcap/meta.nix b/modules/applications/normcap/meta.nix deleted file mode 100644 index e59654b..0000000 --- a/modules/applications/normcap/meta.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ - description = "NormCap OCR screen capture"; - - includes = [ - "applications.nani" - ]; -} diff --git a/modules/profiles/interface/linux-desktop/meta.nix b/modules/profiles/interface/linux-desktop/meta.nix index 3ccb5fc..c1fcce7 100644 --- a/modules/profiles/interface/linux-desktop/meta.nix +++ b/modules/profiles/interface/linux-desktop/meta.nix @@ -13,7 +13,7 @@ "applications.loupe" "applications.linux-wallpaperengine" "applications.nautilus" - "applications.normcap" + "applications.nani" "applications.papers" "applications.qalculate-gtk" "applications.resources"