diff --git a/krebs/5pkgs/simple/flameshot-once/config.nix b/krebs/5pkgs/simple/flameshot-once/config.nix new file mode 100644 index 000000000..817c700a1 --- /dev/null +++ b/krebs/5pkgs/simple/flameshot-once/config.nix @@ -0,0 +1,408 @@ +{ config, pkgs, ... }: +with pkgs.stockholm.lib; + +let + # Encode integer to C-escaped string of bytes, little endian / LSB 0 + le = rec { + x1 = i: let + i0 = mod i 16; + i1 = i / 16; + in + if i == 0 then + "\\0" + else if i < 16 then + "\\x${elemAt hexchars i0}" + else + "\\x${elemAt hexchars i1}${elemAt hexchars i0}"; + + x2 = i: let + i0 = mod i 256; + i1 = i / 256; + in + "${x1 i1}${x1 i0}"; + + x4 = i: let + i0 = mod i 65536; + i1 = i / 65536; + in + "${x2 i1}${x2 i0}"; + }; + + toQList = t: xs: + assert t == "int"; + "QList<${t}>${le.x4 0}${le.x1 (length xs)}${concatMapStrings le.x4 xs}"; +in + +{ + options = { + imgur = mkOption { + default = {}; + type = types.submodule { + options = { + enable = mkEnableOption "imgur"; + createUrl = mkOption { + example = "http://p.r/image"; + type = types.str; + }; + deleteUrl = mkOption { + example = "http://p.r/image/delete/%1"; + type = types.str; + }; + xdg-open = mkOption { + default = {}; + type = types.submodule { + options = { + enable = mkEnableOption "imgur.xdg-open" // { + default = true; + }; + browser = mkOption { + default = "${pkgs.coreutils}/bin/false"; + type = types.str; + }; + createPrefix = mkOption { + default = config.imgur.createUrl; + type = types.str; + }; + deletePrefix = mkOption { + default = removeSuffix "/%1" config.imgur.deleteUrl; + type = types.str; + }; + }; + }; + }; + }; + }; + }; + package = mkOption { + type = types.package; + default = import ./flameshot { inherit pkgs; }; + }; + settings = { + # Options without a description are not documented in flameshot's README. + General = mapAttrs (_: recursiveUpdate { default = null; }) { + allowMultipleGuiInstances = mkOption { + description = '' + Allow multiple instances of `flameshot gui` to run at the same time + ''; + type = with types; nullOr bool; + }; + antialiasingPinZoom = mkOption { + description = '' + Anti-aliasing image when zoom the pinned image + ''; + type = with types; nullOr bool; + }; + autoCloseIdleDaemon = mkOption { + description = '' + Automatically close daemon when it's not needed + ''; + type = with types; nullOr bool; + }; + buttons = let + buttonTypes = { + TYPE_PENCIL = 0; + TYPE_DRAWER = 1; + TYPE_ARROW = 2; + TYPE_SELECTION = 3; + TYPE_RECTANGLE = 4; + TYPE_CIRCLE = 5; + TYPE_MARKER = 6; + TYPE_SELECTIONINDICATOR = 7; + TYPE_MOVESELECTION = 8; + TYPE_UNDO = 9; + TYPE_COPY = 10; + TYPE_SAVE = 11; + TYPE_EXIT = 12; + TYPE_IMAGEUPLOADER = 13; + TYPE_OPEN_APP = 14; + TYPE_PIXELATE = 15; + TYPE_REDO = 16; + TYPE_PIN = 17; + TYPE_TEXT = 18; + TYPE_CIRCLECOUNT = 19; + TYPE_SIZEINCREASE = 20; + TYPE_SIZEDECREASE = 21; + TYPE_INVERT = 22; + TYPE_ACCEPT = 23; + }; + iterableButtonTypes = [ + "TYPE_ACCEPT" + "TYPE_ARROW" + "TYPE_CIRCLE" + "TYPE_CIRCLECOUNT" + "TYPE_COPY" + "TYPE_DRAWER" + "TYPE_EXIT" + "TYPE_IMAGEUPLOADER" + "TYPE_MARKER" + "TYPE_MOVESELECTION" + "TYPE_OPEN_APP" + "TYPE_PENCIL" + "TYPE_PIN" + "TYPE_PIXELATE" + "TYPE_RECTANGLE" + "TYPE_REDO" + "TYPE_SAVE" + "TYPE_SELECTION" + "TYPE_SIZEDECREASE" + "TYPE_SIZEINCREASE" + "TYPE_TEXT" + "TYPE_UNDO" + ]; + in mkOption { + apply = names: + if names != null then let + values = map (name: buttonTypes.${name}) names; + in + ''@Variant(\0\0\0\x7f\0\0\0\v${toQList "int" values})'' + else + null; + description = '' + Configure which buttons to show after drawing a selection + ''; + type = with types; nullOr (listOf (enum iterableButtonTypes)); + }; + checkForUpdates = mkOption { + type = with types; nullOr bool; + }; + contrastOpacity = mkOption { + description = '' + Opacity of area outside selection + ''; + type = with types; nullOr (boundedInt 0 255); + }; + contrastUiColor = mkOption { + description = '' + Contrast UI color + ''; + type = with types; nullOr flameshot.color; + }; + copyAndCloseAfterUpload = mkOption { + type = with types; nullOr bool; + }; + copyOnDoubleClick = mkOption { + type = with types; nullOr bool; + }; + copyPathAfterSave = mkOption { + description = '' + Copy path to image after save + ''; + type = with types; nullOr bool; + }; + copyURLAfterUpload = mkOption { + description = '' + On successful upload, close the dialog and copy URL to clipboard + ''; + type = with types; nullOr bool; + }; + disabledTrayIcon = mkOption { + description = '' + Whether the tray icon is disabled + ''; + type = with types; nullOr bool; + }; + drawColor = mkOption { + description = '' + Last used color + ''; + type = with types; nullOr flameshot.color; + }; + drawFontSize = mkOption { + type = with types; nullOr positive; + }; + drawThickness = mkOption { + description = '' + Last used tool thickness + ''; + type = with types; nullOr positive; + }; + filenamePattern = mkOption { + description = '' + Filename pattern using C++ strftime formatting + ''; + type = + # This is types.filename extended by [%:][%:+]* + with types; + nullOr (addCheck str (test "[%:0-9A-Za-z._][%:+0-9A-Za-z._-]*")); + }; + fontFamily = mkOption { + type = with types; nullOr str; + }; + historyConfirmationToDelete = mkOption { + type = with types; nullOr bool; + }; + ignoreUpdateToVersion = mkOption { + description = '' + Ignore updates to versions less than this value + ''; + type = with types; nullOr str; + }; + keepOpenAppLauncher = mkOption { + description = '' + Keep the App Launcher open after selecting an app + ''; + type = with types; nullOr bool; + }; + predefinedColorPaletteLarge = mkOption { + description = '' + Use larger color palette as the default one + ''; + type = with types; nullOr bool; + }; + saveAfterCopy = mkOption { + description = '' + Save image after copy + ''; + type = with types; nullOr bool; + }; + saveAsFileExtension = mkOption { + description = '' + Default file extension for screenshots + ''; + type = with types; nullOr (addCheck filename (hasPrefix ".")); + }; + safeLastRegion = mkOption { + type = with types; nullOr bool; + }; + savePath = mkOption { + description = '' + Image Save Path + ''; + type = with types; nullOr absolute-pathname; + }; + savePathFixed = mkOption { + description = '' + Whether the savePath is a fixed path + ''; + type = with types; nullOr bool; + }; + showDesktopNotification = mkOption { + description = '' + Show desktop notifications + ''; + type = with types; nullOr bool; + }; + showHelp = mkOption { + description = '' + Show the help screen on startup + ''; + type = with types; nullOr bool; + }; + showMagnifier = mkOption { + type = with types; nullOr bool; + }; + showSelectionGeometry = mkOption { + type = with types; nullOr (boundedInt 0 5); + }; + showSelectionGeometryHideTime = mkOption { + type = with types; nullOr uint; + }; + showSidePanelButton = mkOption { + description = '' + Show the side panel button + ''; + type = with types; nullOr bool; + }; + showStartupLaunchMessage = mkOption { + type = with types; nullOr bool; + }; + squareMagnifier = mkOption { + type = with types; nullOr bool; + }; + startupLaunch = mkOption { + description = '' + Launch at startup + ''; + type = with types; nullOr bool; + }; + uiColor = mkOption { + description = '' + Main UI color + ''; + type = with types; nullOr flameshot.color; + }; + undoLimit = mkOption { + type = with types; nullOr (boundedInt 0 999); + }; + uploadClientSecret = mkOption { + type = with types; nullOr str; + }; + uploadHistoryMax = mkOption { + type = with types; nullOr uint; + }; + uploadWithoutConfirmation = mkOption { + description = '' + Upload to imgur without confirmation + ''; + type = with types; nullOr bool; + }; + useJpgForClipboard = mkOption { + description = '' + Use JPG format instead of PNG + ''; + type = with types; nullOr bool; + }; + userColors = mkOption { + apply = value: + if value != null then + concatStringsSep ", " value + else + null; + description = '' + List of colors for color picker + The colors are arranged counter-clockwise with the first being set + to the right of the cursor. "picker" adds a custom color picker. + ''; + type = + with types; + nullOr (listOf (either flameshot.color (enum ["picker"]))); + }; + }; + Shortcuts = genAttrs [ + "TYPE_ACCEPT" + "TYPE_ARROW" + "TYPE_CIRCLE" + "TYPE_CIRCLECOUNT" + "TYPE_COMMIT_CURRENT_TOOL" + "TYPE_COPY" + "TYPE_DELETE_CURRENT_TOOL" + "TYPE_DRAWER" + "TYPE_EXIT" + "TYPE_IMAGEUPLOADER" + "TYPE_INVERT" + "TYPE_MARKER" + "TYPE_MOVESELECTION" + "TYPE_MOVE_DOWN" + "TYPE_MOVE_LEFT" + "TYPE_MOVE_RIGHT" + "TYPE_MOVE_UP" + "TYPE_OPEN_APP" + "TYPE_PENCIL" + "TYPE_PIN" + "TYPE_PIXELATE" + "TYPE_RECTANGLE" + "TYPE_REDO" + "TYPE_RESIZE_DOWN" + "TYPE_RESIZE_LEFT" + "TYPE_RESIZE_RIGHT" + "TYPE_RESIZE_UP" + "TYPE_SAVE" + "TYPE_SELECTION" + "TYPE_SELECTIONINDICATOR" + "TYPE_SELECT_ALL" + "TYPE_SIZEDECREASE" + "TYPE_SIZEINCREASE" + "TYPE_SYM_RESIZE_DOWN" + "TYPE_SYM_RESIZE_LEFT" + "TYPE_SYM_RESIZE_RIGHT" + "TYPE_SYM_RESIZE_UP" + "TYPE_TEXT" + "TYPE_TOGGLE_PANEL" + "TYPE_UNDO" + ] (name: mkOption { + default = null; + type = with types; nullOr str; + }); + }; + }; +} diff --git a/krebs/5pkgs/simple/flameshot-once/default.nix b/krebs/5pkgs/simple/flameshot-once/default.nix new file mode 100644 index 000000000..92dd5311f --- /dev/null +++ b/krebs/5pkgs/simple/flameshot-once/default.nix @@ -0,0 +1,71 @@ +{ name ? "flameshot-once", pkgs, ... }@args: +with pkgs.stockholm.lib; + +let + # config cannot be declared in the input attribute set because that would + # cause callPackage to inject the wrong config. Instead, get it from ... + # via args. + config = args.config or {}; + + cfg = evalModulesConfig (singleton { + _file = toString ./default.nix; + _module.args.pkgs = pkgs; + imports = [ + config + ./config.nix + ]; + }); +in + +pkgs.symlinkJoin { + inherit name; + paths = [ + (pkgs.write "flameshot-once" { + "/bin/flameshot-once" = { + executable = true; + text = /* sh */ '' + #! ${pkgs.dash}/bin/dash + export PATH=${makeBinPath [ + pkgs.qt5.qtbase + ]}:''${PATH+:$PATH} + ${optionalString (config != null) /* sh */ '' + export XDG_CONFIG_HOME=${placeholder "out"}/etc + ${optionalString cfg.imgur.enable /* sh */ '' + export IMGUR_CREATE_URL=${shell.escape cfg.imgur.createUrl} + export IMGUR_DELETE_URL=${shell.escape cfg.imgur.deleteUrl} + ${optionalString cfg.imgur.xdg-open.enable /* sh */ '' + export PATH=${placeholder "out"}/lib/imgur/bin''${PATH+:$PATH} + ''} + ''} + ''} + ${cfg.package}/bin/flameshot & + exec ${cfg.package}/bin/flameshot gui + ''; + }; + "/etc/flameshot/flameshot.ini".text = + lib.generators.toINI {} (stripAttr cfg.settings); + ${if cfg.imgur.enable then "/lib/imgur/bin/xdg-open" else null} = { + executable = true; + text = /* sh */ '' + #! ${pkgs.dash}/bin/dash + set -efu + uri=$1 + prefix=$(${pkgs.coreutils}/bin/dirname "$uri") + case $prefix in + (${shell.escape cfg.imgur.xdg-open.createPrefix}) + echo "opening image in browser: $uri" >&2 + exec ${config.imgur.xdg-open.browser} "$uri" + ;; + (${shell.escape cfg.imgur.xdg-open.deletePrefix}) + echo "deleting image: $uri" >&2 + exec ${pkgs.curl}/bin/curl -fsS -X DELETE "$uri" + ;; + (*) + echo "don't know how to open URI: $uri" >&2 + exit 1 + esac + ''; + }; + }) + ]; +} diff --git a/krebs/5pkgs/simple/flameshot-once/flameshot/default.nix b/krebs/5pkgs/simple/flameshot-once/flameshot/default.nix new file mode 100644 index 000000000..b129270eb --- /dev/null +++ b/krebs/5pkgs/simple/flameshot-once/flameshot/default.nix @@ -0,0 +1,15 @@ +{ pkgs }: + +pkgs.flameshot.overrideAttrs (old: rec { + name = "flameshot-${version}"; + version = "12.1.0-pre"; + src = pkgs.fetchFromGitHub { + owner = "flameshot-org"; + repo = "flameshot"; + rev = "f7e41f4d708e50eeaec892408069da25a28e04a2"; + hash = "sha256-fZquXY0xSaN1hJgCh16MocIlvxHe1c2Nt+fGF2NIOVw="; + }; + patches = old.patches or [] ++ [ + ./flameshot-12.imgur.patch + ]; +}) diff --git a/krebs/5pkgs/simple/flameshot-once/flameshot/flameshot-12.imgur.patch b/krebs/5pkgs/simple/flameshot-once/flameshot/flameshot-12.imgur.patch new file mode 100644 index 000000000..b6c3f497a --- /dev/null +++ b/krebs/5pkgs/simple/flameshot-once/flameshot/flameshot-12.imgur.patch @@ -0,0 +1,43 @@ +diff --git a/src/tools/imgupload/storages/imgur/imguruploader.cpp b/src/tools/imgupload/storages/imgur/imguruploader.cpp +index d6748b5a..5bb8d7de 100644 +--- a/src/tools/imgupload/storages/imgur/imguruploader.cpp ++++ b/src/tools/imgupload/storages/imgur/imguruploader.cpp +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + ImgurUploader::ImgurUploader(const QPixmap& capture, QWidget* parent) + : ImgUploaderBase(capture, parent) +@@ -70,7 +71,13 @@ void ImgurUploader::upload() + QString description = FileNameHandler().parsedPattern(); + urlQuery.addQueryItem(QStringLiteral("description"), description); + +- QUrl url(QStringLiteral("https://api.imgur.com/3/image")); ++ const char *IMGUR_CREATE_URL = secure_getenv("IMGUR_CREATE_URL"); ++ QString createUrlPattern = ++ IMGUR_CREATE_URL != NULL ++ ? QString::fromUtf8(IMGUR_CREATE_URL) ++ : QStringLiteral("https://api.imgur.com/3/image") ++ ; ++ QUrl url(createUrlPattern); + url.setQuery(urlQuery); + QNetworkRequest request(url); + request.setHeader(QNetworkRequest::ContentTypeHeader, +@@ -87,8 +94,14 @@ void ImgurUploader::deleteImage(const QString& fileName, + const QString& deleteToken) + { + Q_UNUSED(fileName) ++ const char *IMGUR_DELETE_URL = secure_getenv("IMGUR_DELETE_URL"); ++ QString deleteImageURLPattern = ++ IMGUR_DELETE_URL != NULL ++ ? QString::fromUtf8(IMGUR_DELETE_URL) ++ : QStringLiteral("https://imgur.com/delete/%1") ++ ; + bool successful = QDesktopServices::openUrl( +- QUrl(QStringLiteral("https://imgur.com/delete/%1").arg(deleteToken))); ++ QUrl(deleteImageURLPattern.arg(deleteToken))); + if (!successful) { + notification()->showMessage(tr("Unable to open the URL.")); + } diff --git a/lib/types.nix b/lib/types.nix index 4bb8c173f..5f01ccb52 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -7,7 +7,7 @@ let mkOption mkOptionType optional optionalAttrs optionals range splitString stringLength substring test testString typeOf; inherit (lib.types) - attrsOf bool either enum int lines listOf nullOr path str submodule; + addCheck attrsOf bool either enum int lines listOf nullOr path str submodule; in rec { @@ -595,6 +595,9 @@ rec { }; }; + flameshot.color = + either (addCheck str (test "#[0-9A-Fa-f]{6}")) svg.color-keyword; + file-mode = mkOptionType { name = "file mode"; check = test "[0-7]{4}"; diff --git a/tv/5pkgs/haskell/flameshot-once.nix b/tv/5pkgs/haskell/flameshot-once.nix deleted file mode 100644 index c8007ce9e..000000000 --- a/tv/5pkgs/haskell/flameshot-once.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ mkDerivation, async, base, blessings, bytestring, dbus, fetchgit -, iso8601-time, lib, process, random, text, time, unagi-chan, unix -}: -mkDerivation { - pname = "flameshot-once"; - version = "1.4.0"; - src = fetchgit { - url = "https://cgit.krebsco.de/flameshot-once"; - sha256 = "13szgsiwn29aixm5xvs1m7128y5km5xss0ry5ii5y068rc2vysw8"; - rev = "4475893c2081b3d9db4b7a54d0ce38d0914a17bf"; - fetchSubmodules = true; - }; - isLibrary = false; - isExecutable = true; - executableHaskellDepends = [ - async base blessings bytestring dbus iso8601-time process random - text time unagi-chan unix - ]; - license = lib.licenses.mit; -} diff --git a/tv/5pkgs/override/flameshot/default.nix b/tv/5pkgs/override/flameshot/default.nix deleted file mode 100644 index 10154cc44..000000000 --- a/tv/5pkgs/override/flameshot/default.nix +++ /dev/null @@ -1,15 +0,0 @@ -self: super: - -super.flameshot.overrideAttrs (old: rec { - name = "flameshot-${version}"; - version = "0.10.2"; - src = self.fetchFromGitHub { - owner = "flameshot-org"; - repo = "flameshot"; - rev = "v${version}"; - sha256 = "sha256-rZUiaS32C77tFJmEkw/9MGbVTVscb6LOCyWaWO5FyR4="; - }; - patches = old.patches or [] ++ [ - ./flameshot_imgur_0.10.2.patch - ]; -}) diff --git a/tv/5pkgs/override/flameshot/flameshot_imgur_0.10.2.patch b/tv/5pkgs/override/flameshot/flameshot_imgur_0.10.2.patch deleted file mode 100644 index c4c0bf38a..000000000 --- a/tv/5pkgs/override/flameshot/flameshot_imgur_0.10.2.patch +++ /dev/null @@ -1,35 +0,0 @@ ---- a/src/tools/imgur/imguruploader.cpp -+++ b/src/tools/imgur/imguruploader.cpp -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - - ImgurUploader::ImgurUploader(const QPixmap& capture, QWidget* parent) - : QWidget(parent) -@@ -79,8 +80,11 @@ void ImgurUploader::handleReply(QNetworkReply* reply) - m_imageURL.setUrl(data[QStringLiteral("link")].toString()); - - auto deleteToken = data[QStringLiteral("deletehash")].toString(); -+ char *deleteImageURLPattern = secure_getenv("IMGUR_DELETE_URL"); -+ if (deleteImageURLPattern == NULL) -+ deleteImageURLPattern = "https://imgur.com/delete/%1"; - m_deleteImageURL.setUrl( -- QStringLiteral("https://imgur.com/delete/%1").arg(deleteToken)); -+ QString::fromUtf8(deleteImageURLPattern).arg(deleteToken)); - - // save history - QString imageName = m_imageURL.toString(); -@@ -133,7 +137,10 @@ void ImgurUploader::upload() - QString description = FileNameHandler().parsedPattern(); - urlQuery.addQueryItem(QStringLiteral("description"), description); - -- QUrl url(QStringLiteral("https://api.imgur.com/3/image")); -+ char *createImageURLPattern = secure_getenv("IMGUR_CREATE_URL"); -+ if (createImageURLPattern == NULL) -+ createImageURLPattern = "https://api.imgur.com/3/image"; -+ QUrl url(QString::fromUtf8(createImageURLPattern)); - url.setQuery(urlQuery); - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::ContentTypeHeader, diff --git a/tv/5pkgs/simple/flameshot-once/default.nix b/tv/5pkgs/simple/flameshot-once/default.nix deleted file mode 100644 index 0524c2cfa..000000000 --- a/tv/5pkgs/simple/flameshot-once/default.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ pkgs, stockholm, ... }@args: -with stockholm.lib; - -let - # config cannot be declared in the input attribute set because that would - # cause callPackage to inject the wrong config. Instead, get it from ... - # via args. - config = args.config or {}; -in - - pkgs.symlinkJoin { - name = "flameshot-once-wrapper"; - paths = [ - (pkgs.writeDashBin "flameshot-once" '' - export PATH=${makeBinPath [ - pkgs.flameshot - pkgs.qt5.qtbase - pkgs.xclip - pkgs.xwaitforwindow - ]} - ${optionalString (config != null) /* sh */ '' - . ${import ./profile.nix { inherit config pkgs; }} - ''} - exec ${pkgs.haskellPackages.flameshot-once}/bin/flameshot-once "$@" - '') - pkgs.haskellPackages.flameshot-once - ]; - } diff --git a/tv/5pkgs/simple/flameshot-once/profile.nix b/tv/5pkgs/simple/flameshot-once/profile.nix deleted file mode 100644 index 269f13a66..000000000 --- a/tv/5pkgs/simple/flameshot-once/profile.nix +++ /dev/null @@ -1,235 +0,0 @@ -{ config, pkgs }: -with pkgs.stockholm.lib; -with generators; -let - - # Refs https://github.com/lupoDharkael/flameshot/blob/master/src/widgets/capture/capturebutton.h - ButtonType = { - PENCIL = 0; - DRAWER = 1; - ARROW = 2; - SELECTION = 3; - RECTANGLE = 4; - CIRCLE = 5; - MARKER = 6; - SELECTIONINDICATOR = 7; - MOVESELECTION = 8; - UNDO = 9; - COPY = 10; - SAVE = 11; - EXIT = 12; - IMAGEUPLOADER = 13; - OPEN_APP = 14; - BLUR = 15; - REDO = 16; - PIN = 17; - TEXT = 18; - CIRCLECOUNT = 19; - }; - - cfg = eval.config; - - eval = evalModules { - modules = singleton { - _file = toString ./profile.nix; - imports = singleton config; - options = { - buttons = mkOption { - apply = map (name: ButtonType.${name}); - default = [ - "PENCIL" - "DRAWER" - "ARROW" - "SELECTION" - "RECTANGLE" - "CIRCLE" - "MARKER" - "SELECTIONINDICATOR" - "MOVESELECTION" - "UNDO" - "SAVE" - "EXIT" - "BLUR" - "CIRCLECOUNT" - ] - ++ optional cfg.imgur.enable "IMAGEUPLOADER" - ; - type = types.listOf (types.enum (attrNames ButtonType)); - }; - copyAndCloseAfterUpload = mkOption { - default = false; - type = types.bool; - }; - disabledTrayIcon = mkOption { - default = true; - type = types.bool; - }; - drawColor = mkOption { - default = "#ff0000"; - type = - types.addCheck types.str (test "#[0-9A-Fa-f]{6}"); - }; - drawThickness = mkOption { - default = 8; - type = types.positive; - }; - filenamePattern = mkOption { - default = "%FT%T%z_flameshot"; - type = - # This is types.filename extended by [%:][%:+]* - types.addCheck types.str (test "[%:0-9A-Za-z._][%:+0-9A-Za-z._-]*"); - }; - imgur = mkOption { - default = {}; - type = types.submodule { - options = { - enable = mkEnableOption "imgur"; - createUrl = mkOption { - example = "http://p.r/image"; - type = types.str; - }; - deleteUrl = mkOption { - example = "http://p.r/image/delete/%1"; - type = types.str; - }; - xdg-open = mkOption { - default = {}; - type = types.submodule { - options = { - enable = mkEnableOption "imgur.xdg-open" // { - default = true; - }; - browser = mkOption { - default = "${pkgs.coreutils}/bin/false"; - type = types.str; - }; - createPrefix = mkOption { - default = cfg.imgur.createUrl; - type = types.str; - }; - deletePrefix = mkOption { - default = removeSuffix "/%1" cfg.imgur.deleteUrl; - type = types.str; - }; - }; - }; - }; - }; - }; - }; - savePath = mkOption { - default = "/tmp"; - type = types.absolute-pathname; - }; - showDesktopNotification = mkOption { - default = false; - type = types.bool; - }; - showHelp = mkOption { - default = false; - type = types.bool; - }; - showSidePanelButton = mkOption { - default = false; - type = types.bool; - }; - showStartupLaunchMessage = mkOption { - default = false; - type = types.bool; - }; - timeout = mkOption { - default = 200; - description = '' - Maximum time in milliseconds allowed for the flameshot daemon to - react. - ''; - type = types.positive; - }; - }; - }; - }; - - hexchars = stringToCharacters "0123456789abcdef"; - - # Encode integer to C-escaped string of bytes, little endian / LSB 0 - le = rec { - x1 = i: let - i0 = mod i 16; - i1 = i / 16; - in - "\\x${elemAt hexchars i1}${elemAt hexchars i0}"; - - x2 = i: let - i0 = mod i 256; - i1 = i / 256; - in - "${x1 i0}${x1 i1}"; - - x4 = i: let - i0 = mod i 65536; - i1 = i / 65536; - in - "${x2 i0}${x2 i1}"; - }; - - toQList = t: xs: - assert t == "int"; - "QList<${t}>${le.x4 0}${le.x4 (length xs)}${concatMapStrings le.x4 xs}"; - - XDG_CONFIG_HOME = pkgs.write "flameshot-config" { - "/flameshot/flameshot.ini".text = - toINI {} { - General = { - buttons = ''@Variant(\0\0\0\x7f\0\0\0\v${toQList "int" cfg.buttons})''; - disabledTrayIcon = cfg.disabledTrayIcon; - checkForUpdates = false; - copyAndCloseAfterUpload = cfg.copyAndCloseAfterUpload; - drawColor = cfg.drawColor; - drawThickness = cfg.drawThickness; - filenamePattern = cfg.filenamePattern; - savePath = cfg.savePath; - showDesktopNotification = cfg.showDesktopNotification; - showHelp = cfg.showHelp; - showSidePanelButton = cfg.showSidePanelButton; - showStartupLaunchMessage = cfg.showStartupLaunchMessage; - startupLaunch = false; - }; - Shortcuts = { - TYPE_COPY = "Return"; - }; - }; - }; - -in - - pkgs.writeDash "flameshot.profile" '' - export FLAMESHOT_CAPTURE_PATH=${cfg.savePath} - export FLAMESHOT_ONCE_TIMEOUT=${toString cfg.timeout} - export XDG_CONFIG_HOME=${XDG_CONFIG_HOME} - ${optionalString cfg.imgur.enable /* sh */ '' - export IMGUR_CREATE_URL=${shell.escape cfg.imgur.createUrl} - export IMGUR_DELETE_URL=${shell.escape cfg.imgur.deleteUrl} - ${optionalString cfg.imgur.xdg-open.enable /* sh */ '' - PATH=$PATH:${makeBinPath [ - (pkgs.writeDashBin "xdg-open" '' - set -efu - uri=$1 - prefix=$(${pkgs.coreutils}/bin/dirname "$uri") - case $prefix in - (${shell.escape cfg.imgur.xdg-open.createPrefix}) - echo "opening image in browser: $uri" >&2 - exec ${config.imgur.xdg-open.browser} "$uri" - ;; - (${shell.escape cfg.imgur.xdg-open.deletePrefix}) - echo "deleting image: $uri" >&2 - exec ${pkgs.curl}/bin/curl -fsS -X DELETE "$uri" - ;; - (*) - echo "don't know how to open URI: $uri" >&2 - exit 1 - esac - '') - ]} - ''} - ''} - ''