179 lines
3.9 KiB
Nix
179 lines
3.9 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
inherit (lib)
|
|
mkOption
|
|
mkAliasOptionModule
|
|
types
|
|
mapAttrsToList
|
|
attrNames
|
|
filterAttrs
|
|
replaceStrings
|
|
getExe
|
|
toLower
|
|
;
|
|
inherit (types)
|
|
str
|
|
strMatching
|
|
package
|
|
path
|
|
nullOr
|
|
listOf
|
|
attrsOf
|
|
submodule
|
|
either
|
|
;
|
|
|
|
browser = getExe config.apps.browser;
|
|
|
|
webAppLauncher = pkgs.writeShellScript "web-app-launcher" ''
|
|
browser="${browser}"
|
|
|
|
browser_exec=""
|
|
for path in ~/.local ~/.nix-profile /usr /nix/var/nix/profiles/system/etc/profiles/per-user/$USER; do
|
|
if [ -f "$path/share/applications/$browser.desktop" ]; then
|
|
browser_exec=$(sed -n 's/^Exec=\([^ ]*\).*/\1/p' "$path/share/applications/$browser.desktop" 2>/dev/null | head -1)
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -z "$browser_exec" ]; then
|
|
browser_exec="${browser}"
|
|
fi
|
|
|
|
url="$1"
|
|
app_name="''${2:-$(basename "$0")}"
|
|
shift 2
|
|
|
|
exec setsid "$browser_exec" \
|
|
--app="$url" \
|
|
--user-data-dir="$HOME/.local/share/web-apps/$app_name" \
|
|
--no-first-run \
|
|
--no-default-browser-check \
|
|
--disable-background-timer-throttling \
|
|
--disable-backgrounding-occluded-windows \
|
|
--disable-renderer-backgrounding \
|
|
--enable-quic \
|
|
--quic-version=h3-29 \
|
|
--enable-features=UseOzonePlatform,WaylandWindowDecorations,WaylandPerWindowScaling,WaylandTextInputV3,WebRTCPipeWireCapturer \
|
|
--disable-features=WebRtcAllowInputVolumeAdjustment \
|
|
--ozone-platform=wayland \
|
|
--gtk-version=4 \
|
|
--enable-experimental-web-platform-features \
|
|
"$@"
|
|
'';
|
|
|
|
# Create web app package
|
|
mkWebApp =
|
|
{
|
|
name,
|
|
url,
|
|
icon,
|
|
description,
|
|
categories,
|
|
}:
|
|
let
|
|
cleanName = replaceStrings [ " " "\n" "\t" ] [ "-" "-" "-" ] name |> toLower;
|
|
pname = "${cleanName}-webapp";
|
|
in
|
|
pkgs.stdenv.mkDerivation {
|
|
inherit pname;
|
|
version = "1.0";
|
|
dontUnpack = true;
|
|
|
|
nativeBuildInputs = [
|
|
pkgs.copyDesktopItems
|
|
pkgs.makeWrapper
|
|
];
|
|
|
|
installPhase = ''
|
|
runHook preInstall
|
|
makeWrapper ${webAppLauncher} $out/bin/${pname} \
|
|
--add-flags "${url}" \
|
|
--add-flags "${pname}"
|
|
runHook postInstall
|
|
'';
|
|
|
|
desktopItems = [
|
|
(pkgs.makeDesktopItem (
|
|
{
|
|
name = pname;
|
|
exec = "${pname} %U";
|
|
desktopName = name;
|
|
startupNotify = true;
|
|
startupWMClass = pname;
|
|
}
|
|
// filterAttrs (_: v: v != null) {
|
|
inherit icon categories;
|
|
comment = description;
|
|
}
|
|
))
|
|
];
|
|
|
|
meta.mainProgram = pname;
|
|
|
|
};
|
|
|
|
innerOpts = {
|
|
options = {
|
|
name = mkOption {
|
|
type = str;
|
|
};
|
|
url = mkOption {
|
|
type = strMatching "[hH][tT][tT][pP][sS]?://[^\n\r[:space:]]+";
|
|
};
|
|
icon = mkOption {
|
|
type = nullOr (either str path);
|
|
default = null;
|
|
};
|
|
description = mkOption {
|
|
type = nullOr str;
|
|
default = null;
|
|
};
|
|
categories = mkOption {
|
|
type = nullOr (listOf str);
|
|
default = null;
|
|
};
|
|
};
|
|
};
|
|
|
|
pwaModule = submodule (
|
|
{ config, ... }:
|
|
{
|
|
imports =
|
|
let
|
|
names = innerOpts.options |> attrNames;
|
|
in
|
|
map (optName: mkAliasOptionModule [ optName ] [ "settings" optName ]) names;
|
|
options = {
|
|
settings = mkOption {
|
|
type = submodule innerOpts;
|
|
default = { };
|
|
};
|
|
package = mkOption {
|
|
type = package;
|
|
readOnly = true;
|
|
default = mkWebApp config.settings;
|
|
};
|
|
};
|
|
}
|
|
);
|
|
|
|
in
|
|
{
|
|
options = {
|
|
programs.pwas = mkOption {
|
|
description = "PWA Applications";
|
|
type = attrsOf pwaModule;
|
|
default = { };
|
|
};
|
|
};
|
|
|
|
config = {
|
|
environment.systemPackages = mapAttrsToList (_: v: v.package) config.programs.pwas;
|
|
};
|
|
}
|