nixos: add affinity thumbnailer for kde
This commit is contained in:
Generated
+17
@@ -28,6 +28,22 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"affinity-thumbnailer-kde": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"path": "./packages/affinity-thumbnailer-kde",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"path": "./packages/affinity-thumbnailer-kde",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
"parent": []
|
||||||
|
},
|
||||||
"appimage-manager": {
|
"appimage-manager": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_4"
|
"nixpkgs": "nixpkgs_4"
|
||||||
@@ -705,6 +721,7 @@
|
|||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"affinity-nix": "affinity-nix",
|
"affinity-nix": "affinity-nix",
|
||||||
|
"affinity-thumbnailer-kde": "affinity-thumbnailer-kde",
|
||||||
"appimage-manager": "appimage-manager",
|
"appimage-manager": "appimage-manager",
|
||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
"i915-sriov-dkms": "i915-sriov-dkms",
|
"i915-sriov-dkms": "i915-sriov-dkms",
|
||||||
|
|||||||
@@ -22,6 +22,11 @@
|
|||||||
|
|
||||||
affinity-nix.url = "github:mrshmllow/affinity-nix";
|
affinity-nix.url = "github:mrshmllow/affinity-nix";
|
||||||
|
|
||||||
|
affinity-thumbnailer-kde = {
|
||||||
|
url = "path:./packages/affinity-thumbnailer-kde";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
scopebuddy.url = "github:HikariKnight/ScopeBuddy";
|
scopebuddy.url = "github:HikariKnight/ScopeBuddy";
|
||||||
nix-gaming.url = "github:fufexan/nix-gaming";
|
nix-gaming.url = "github:fufexan/nix-gaming";
|
||||||
nixpkgs-xr.url = "github:nix-community/nixpkgs-xr";
|
nixpkgs-xr.url = "github:nix-community/nixpkgs-xr";
|
||||||
@@ -36,6 +41,7 @@
|
|||||||
nix-darwin,
|
nix-darwin,
|
||||||
nix-flatpak,
|
nix-flatpak,
|
||||||
affinity-nix,
|
affinity-nix,
|
||||||
|
affinity-thumbnailer-kde,
|
||||||
i915-sriov-dkms,
|
i915-sriov-dkms,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
@@ -60,6 +66,7 @@
|
|||||||
|
|
||||||
nixpkgs-xr.nixosModules.nixpkgs-xr
|
nixpkgs-xr.nixosModules.nixpkgs-xr
|
||||||
nix-flatpak.nixosModules.nix-flatpak
|
nix-flatpak.nixosModules.nix-flatpak
|
||||||
|
affinity-thumbnailer-kde.nixosModules.default
|
||||||
|
|
||||||
./hosts/nero/hardware.nix
|
./hosts/nero/hardware.nix
|
||||||
./hosts/nero/configuration.nix
|
./hosts/nero/configuration.nix
|
||||||
@@ -74,6 +81,7 @@
|
|||||||
home-manager-configuration
|
home-manager-configuration
|
||||||
|
|
||||||
nix-flatpak.nixosModules.nix-flatpak
|
nix-flatpak.nixosModules.nix-flatpak
|
||||||
|
affinity-thumbnailer-kde.nixosModules.default
|
||||||
i915-sriov-dkms.nixosModules.default
|
i915-sriov-dkms.nixosModules.default
|
||||||
|
|
||||||
./hosts/pdw-frankiel/hardware.nix
|
./hosts/pdw-frankiel/hardware.nix
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
openssh.enable = true;
|
openssh.enable = true;
|
||||||
|
affinity-thumbnailer.enable = true;
|
||||||
|
|
||||||
# Enables m(ulticast)DNS (a.k.a. Bonjour) support.
|
# Enables m(ulticast)DNS (a.k.a. Bonjour) support.
|
||||||
avahi = {
|
avahi = {
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
{
|
||||||
|
description = "Thumbnailer for Affinity files (.afpub, .afdesign, .afphoto, .af, .afpackage) on KDE Plasma / freedesktop";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{ self, nixpkgs }:
|
||||||
|
let
|
||||||
|
systems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
"aarch64-linux"
|
||||||
|
];
|
||||||
|
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = forAllSystems (pkgs: {
|
||||||
|
default = self.packages.${pkgs.stdenv.hostPlatform.system}.affinity-thumbnailer;
|
||||||
|
|
||||||
|
affinity-thumbnailer = pkgs.stdenv.mkDerivation {
|
||||||
|
pname = "affinity-thumbnailer";
|
||||||
|
version = "0.1.0";
|
||||||
|
|
||||||
|
# Don't pull source from GitHub — we build everything from inline content
|
||||||
|
src = pkgs.runCommand "affinity-thumbnailer-src" { } ''
|
||||||
|
mkdir -p $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||||
|
|
||||||
|
# Runtime dependencies
|
||||||
|
buildInputs = [ pkgs.python3 ];
|
||||||
|
|
||||||
|
dontConfigure = true;
|
||||||
|
dontBuild = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
# --- 1. Install the Python thumbnailer script ---
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cat > $out/bin/affinity-thumbnailer << 'PYEOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Extract embedded PNG thumbnails from Affinity files (.afpub, .afdesign, .afphoto, .af, .afpackage)."""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
PNG_SIGNATURE = b"\x89PNG"
|
||||||
|
PNG_IEND = b"IEND"
|
||||||
|
SUPPORTED_EXTENSIONS = {".afpub", ".afdesign", ".afphoto", ".af", ".afpackage"}
|
||||||
|
|
||||||
|
|
||||||
|
def find_png(data: bytes) -> bytes | None:
|
||||||
|
"""Find and extract the first complete PNG from binary data."""
|
||||||
|
sig_offset = data.find(PNG_SIGNATURE)
|
||||||
|
if sig_offset == -1:
|
||||||
|
return None
|
||||||
|
|
||||||
|
iend_offset = data.find(PNG_IEND, sig_offset)
|
||||||
|
if iend_offset == -1:
|
||||||
|
return None
|
||||||
|
|
||||||
|
png_end = iend_offset + len(PNG_IEND) + 4
|
||||||
|
return data[sig_offset:png_end]
|
||||||
|
|
||||||
|
|
||||||
|
def extract_thumbnail(filepath: str) -> bytes | None:
|
||||||
|
"""Read a file and extract its embedded PNG thumbnail."""
|
||||||
|
ext = os.path.splitext(filepath)[1].lower()
|
||||||
|
if ext not in SUPPORTED_EXTENSIONS:
|
||||||
|
print(
|
||||||
|
f"Error: unsupported extension '{ext}'. "
|
||||||
|
f"Supported: {', '.join(sorted(SUPPORTED_EXTENSIONS))}",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not os.path.isfile(filepath):
|
||||||
|
print(f"Error: file not found: {filepath}", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
|
||||||
|
with open(filepath, "rb") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
return find_png(data)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Extract embedded PNG thumbnail from Affinity files."
|
||||||
|
)
|
||||||
|
parser.add_argument("input", help="Input Affinity file (.afpub, .afdesign, .afphoto, .af, .afpackage)")
|
||||||
|
parser.add_argument(
|
||||||
|
"output",
|
||||||
|
nargs="?",
|
||||||
|
default=None,
|
||||||
|
help="Output PNG file (default: stdout)",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
png_data = extract_thumbnail(args.input)
|
||||||
|
if png_data is None:
|
||||||
|
print("Error: no embedded PNG thumbnail found.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if args.output:
|
||||||
|
with open(args.output, "wb") as f:
|
||||||
|
f.write(png_data)
|
||||||
|
print(f"Thumbnail saved: {args.output} ({len(png_data)} bytes)")
|
||||||
|
else:
|
||||||
|
sys.stdout.buffer.write(png_data)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
PYEOF
|
||||||
|
chmod +x $out/bin/affinity-thumbnailer
|
||||||
|
|
||||||
|
# Wrap so it finds python3 in NixOS
|
||||||
|
wrapProgram $out/bin/affinity-thumbnailer \
|
||||||
|
--prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.python3 ]}
|
||||||
|
|
||||||
|
# --- 2. Install the .thumbnailer freedesktop entry ---
|
||||||
|
mkdir -p $out/share/thumbnailers
|
||||||
|
cat > $out/share/thumbnailers/affinity.thumbnailer << EOF
|
||||||
|
[Thumbnailer Entry]
|
||||||
|
TryExec=$out/bin/affinity-thumbnailer
|
||||||
|
Exec=$out/bin/affinity-thumbnailer %i %o
|
||||||
|
MimeType=application/affinity-publisher;application/affinity-designer;application/affinity-photo;application/affinity-v3;application/affinity-package;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# --- 3. Install MIME type definitions ---
|
||||||
|
mkdir -p $out/share/mime/packages
|
||||||
|
cat > $out/share/mime/packages/application-affinity.xml << 'MIMEXML'
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||||
|
<mime-type type="application/affinity-publisher">
|
||||||
|
<comment>Affinity File</comment>
|
||||||
|
<glob pattern="*.afpub"/>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/affinity-designer">
|
||||||
|
<comment>Affinity File</comment>
|
||||||
|
<glob pattern="*.afdesign"/>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/affinity-photo">
|
||||||
|
<comment>Affinity File</comment>
|
||||||
|
<glob pattern="*.afphoto"/>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/affinity-v3">
|
||||||
|
<comment>Affinity File</comment>
|
||||||
|
<glob pattern="*.af"/>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/affinity-package">
|
||||||
|
<comment>Affinity File</comment>
|
||||||
|
<glob pattern="*.afpackage"/>
|
||||||
|
</mime-type>
|
||||||
|
</mime-info>
|
||||||
|
MIMEXML
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
description = "Thumbnailer for Affinity files on KDE Plasma / freedesktop";
|
||||||
|
homepage = "https://github.com/Nczer/Affinity-thumbnailer-KDE-plasma";
|
||||||
|
license = licenses.mit; # No license specified in the repo
|
||||||
|
platforms = platforms.linux;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
# --- NixOS module for easy integration ---
|
||||||
|
nixosModules.default =
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
options.services.affinity-thumbnailer = {
|
||||||
|
enable = lib.mkEnableOption "Affinity file thumbnailer for KDE Plasma / freedesktop";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf config.services.affinity-thumbnailer.enable {
|
||||||
|
environment.systemPackages = [
|
||||||
|
self.packages.${pkgs.stdenv.hostPlatform.system}.default
|
||||||
|
];
|
||||||
|
|
||||||
|
# Make sure thumbnailer and MIME directories are linked
|
||||||
|
environment.pathsToLink = [
|
||||||
|
"/share/thumbnailers"
|
||||||
|
"/share/mime"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user