push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
{
lib,
stdenv,
fetchFromGitHub,
replaceVars,
glib,
gnome-shell,
gettext,
jq,
intltool,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "gnome-shell-extension-EasyScreenCast";
version = "1.11.1";
src = fetchFromGitHub {
owner = "EasyScreenCast";
repo = "EasyScreenCast";
rev = finalAttrs.version;
hash = "sha256-G4JDxaUfipn9asOXGw+OPVULOdV+OmzeK5aE/FSPGes=";
};
patches = [
(replaceVars ./fix-gi-path.patch {
gnomeShell = gnome-shell;
})
];
nativeBuildInputs = [
glib
gettext
jq
intltool
];
makeFlags = [ "INSTALLBASE=$(out)/share/gnome-shell/extensions" ];
passthru.extensionUuid = "EasyScreenCast@iacopodeenosee.gmail.com";
meta = {
description = "Simplifies the use of the video recording function integrated in gnome shell";
homepage = "https://github.com/EasyScreenCast/EasyScreenCast";
license = lib.licenses.gpl3Plus;
maintainers = [ ];
platforms = lib.platforms.linux;
};
})

View File

@@ -0,0 +1,63 @@
diff --git i/extension.js w/extension.js
index c151057..1b6dfc3 100644
--- i/extension.js
+++ w/extension.js
@@ -717,7 +717,7 @@ const EasyScreenCastIndicator = GObject.registerClass({
Lib.TalkativeLog('-*-execute post command');
// launch cmd after registration
- const tmpCmd = `/usr/bin/sh -c "${this._settings.getOption('s', Settings.POST_CMD_SETTING_KEY)}"`;
+ const tmpCmd = `/bin/sh -c "${this._settings.getOption('s', Settings.POST_CMD_SETTING_KEY)}"`;
const mapObj = {
_fpath: pathFile,
diff --git i/prefs.js w/prefs.js
index e0dd1a2..9dcb87a 100644
--- i/prefs.js
+++ w/prefs.js
@@ -13,8 +13,8 @@
'use strict';
import GIRepository from 'gi://GIRepository';
-GIRepository.Repository.prepend_search_path('/usr/lib64/gnome-shell');
-GIRepository.Repository.prepend_library_path('/usr/lib64/gnome-shell');
+GIRepository.Repository.prepend_search_path('@gnomeShell@/lib/gnome-shell');
+GIRepository.Repository.prepend_library_path('@gnomeShell@/lib/gnome-shell');
import Adw from 'gi://Adw';
import GObject from 'gi://GObject';
@@ -713,7 +713,7 @@ const EasyScreenCastSettingsWidget = GObject.registerClass({
Lib.TalkativeLog('-^-NOT SET xdg-user video');
ctx.CtrlExe.Execute(
- '/usr/bin/sh -c "echo $HOME"',
+ '/bin/sh -c "echo $HOME"',
true,
(success, out) => {
Lib.TalkativeLog(`-^-CALLBACK sync S: ${success} out: ${out}`);
@@ -883,7 +883,7 @@ const EasyScreenCastSettingsWidget = GObject.registerClass({
);
ctx.CtrlExe.Execute(
- 'journalctl /usr/bin/gnome-shell --since "15 min ago" --output=cat --no-pager',
+ 'journalctl @gnomeShell@/bin/.gnome-shell-wrapped --since "15 min ago" --output=cat --no-pager',
false,
success => {
Lib.TalkativeLog(`-^-CALLBACK async S= ${success}`);
diff --git i/utilaudio.js w/utilaudio.js
index b07e181..ed7d3ba 100644
--- i/utilaudio.js
+++ w/utilaudio.js
@@ -14,10 +14,8 @@
import GObject from 'gi://GObject';
import GIRepository from 'gi://GIRepository';
-GIRepository.Repository.prepend_search_path('/usr/lib/gnome-shell');
-GIRepository.Repository.prepend_library_path('/usr/lib/gnome-shell');
-GIRepository.Repository.prepend_search_path('/usr/lib64/gnome-shell');
-GIRepository.Repository.prepend_library_path('/usr/lib64/gnome-shell');
+GIRepository.Repository.prepend_search_path('@gnomeShell@/lib/gnome-shell');
+GIRepository.Repository.prepend_library_path('@gnomeShell@/lib/gnome-shell');
import Gvc from 'gi://Gvc';
import * as Lib from './convenience.js';

View File

@@ -0,0 +1,32 @@
# GNOME Shell extensions
All extensions are packaged automatically. They can be found in the `pkgs.gnomeXYExtensions` for XY being a GNOME version. The package names are the extensions UUID, which can be a bit unwieldy to use. `pkgs.gnomeExtensions` is a set of manually curated extensions that match the current `pkgs.gnome-shell` versions. Their name is human-friendly, compared to the other extensions sets. Some of its extensions are manually packaged.
## Automatically packaged extensions
The actual packages are created by `buildGnomeExtension.nix`, provided the correct arguments are fed into it. The important extension data is stored in `extensions.json`, one line/item per extension. That file is generated by running `update-extensions.py`. Furthermore, the automatic generated names are dumped in `collisions.json` for manual inspection. `extensionRenames.nix` contains new names for all extensions that collide.
### Extensions updates
#### For everyday updates,
1. Run `update-extensions.py`.
2. Update `extensionRenames.nix` according to the comment at the top.
#### To package the extensions for new GNOME version,
1. Add a new `gnomeXYExtensions` set in `default.nix`.
2. Update `all-packages.nix` accordingly. (grep for `gnomeExtensions`)
3. Update `supported_versions` in `update-extensions.py`.
4. Follow the [For everyday updates](#for-everyday-updates) section.
#### For GNOME updates,
1. Follow the [To package the extensions for new GNOME version](#to-package-the-extensions-for-new-gnome-version) section if required.
2. Update `versions_to_merge` variable in `./update-extensions.py`.
3. Run `update-extensions.py --skip-fetch`, and update `extensionRenames.nix` according to the comment at the top.
4. Update `gnomeExtensions` in `default.nix` to the new versions.
## Manually packaged extensions
Manually packaged extensions overwrite some of the automatically packaged ones in `pkgs.gnomeExtensions`. They are listed in `manuallyPackaged.nix`, every extension has its own sub-folder.

View File

@@ -0,0 +1,46 @@
{
lib,
stdenv,
fetchFromGitLab,
glib,
gettext,
replaceVars,
gnome-menus,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-arcmenu";
version = "65";
src = fetchFromGitLab {
owner = "arcmenu";
repo = "ArcMenu";
rev = "v${version}";
hash = "sha256-EEK600DwIQAPWR07IMPNZFiWWkiG0blp/D0VKAcc7ns=";
};
patches = [
(replaceVars ./fix_gmenu.patch {
gmenu_path = "${gnome-menus}/lib/girepository-1.0";
})
];
buildInputs = [
glib
gettext
];
makeFlags = [ "INSTALLBASE=${placeholder "out"}/share/gnome-shell/extensions" ];
passthru = {
extensionUuid = "arcmenu@arcmenu.com";
extensionPortalSlug = "arcmenu";
};
meta = with lib; {
description = "Application menu for GNOME Shell, designed to provide a more traditional user experience and workflow";
license = licenses.gpl2Plus;
maintainers = with maintainers; [ dkabot ];
homepage = "https://gitlab.com/arcmenu/ArcMenu";
};
}

View File

@@ -0,0 +1,31 @@
--- a/menuWidgets.js
+++ b/menuWidgets.js
@@ -3,7 +3,11 @@
import Atk from 'gi://Atk';
import Clutter from 'gi://Clutter';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
-import GMenu from 'gi://GMenu';
+
+import GIRepository from 'gi://GIRepository';
+GIRepository.Repository.prepend_search_path('@gmenu_path@');
+const {default: GMenu} = await import('gi://GMenu');
+
import GObject from 'gi://GObject';
import Graphene from 'gi://Graphene';
import Pango from 'gi://Pango';
--- a/menulayouts/baseMenuLayout.js
+++ b/menulayouts/baseMenuLayout.js
@@ -1,7 +1,11 @@
import Clutter from 'gi://Clutter';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
-import GMenu from 'gi://GMenu';
+
+import GIRepository from 'gi://GIRepository';
+GIRepository.Repository.prepend_search_path('@gmenu_path@');
+const {default: GMenu} = await import('gi://GMenu');
+
import GObject from 'gi://GObject';
import Shell from 'gi://Shell';
import St from 'gi://St';

View File

@@ -0,0 +1,36 @@
{
fetchFromGitHub,
lib,
stdenv,
unstableGitUpdater,
}:
stdenv.mkDerivation {
pname = "argos";
version = "unstable-2025-03-27";
src = fetchFromGitHub {
owner = "p-e-w";
repo = "argos";
rev = "13264042ae8b8a6f9f4778c623780e38e5d1cd89";
hash = "sha256-PMMpTaihMHj1FmnjJoZqAhDYVd263M1OZAC+OAnaZEg=";
};
installPhase = ''
mkdir -p "$out/share/gnome-shell/extensions"
cp -a argos@pew.worldwidemann.com "$out/share/gnome-shell/extensions"
'';
passthru = {
extensionUuid = "argos@pew.worldwidemann.com";
extensionPortalSlug = "argos";
updateScript = unstableGitUpdater { };
};
meta = with lib; {
description = "Create GNOME Shell extensions in seconds";
license = licenses.gpl3;
maintainers = with maintainers; [ andersk ];
homepage = "https://github.com/p-e-w/argos";
};
}

View File

@@ -0,0 +1,79 @@
{
pkgs,
lib,
stdenv,
fetchzip,
nixosTests,
}:
let
buildGnomeExtension =
{
# Every gnome extension has a UUID. It's the name of the extension folder once unpacked
# and can always be found in the metadata.json of every extension.
uuid,
name,
pname,
description,
# extensions.gnome.org extension URL
link,
# Extension version numbers are integers
version,
sha256,
# Hex-encoded string of JSON bytes
metadata,
}:
stdenv.mkDerivation {
pname = "gnome-shell-extension-${pname}";
version = toString version;
src = fetchzip {
url = "https://extensions.gnome.org/extension-data/${
builtins.replaceStrings [ "@" ] [ "" ] uuid
}.v${toString version}.shell-extension.zip";
inherit sha256;
stripRoot = false;
# The download URL may change content over time. This is because the
# metadata.json is automatically generated, and parts of it can be changed
# without making a new release. We simply substitute the possibly changed fields
# with their content from when we last updated, and thus get a deterministic output
# hash.
postFetch = ''
echo "${metadata}" | base64 --decode > $out/metadata.json
'';
};
nativeBuildInputs = with pkgs; [ buildPackages.glib ];
buildPhase = ''
runHook preBuild
if [ -d schemas ]; then
glib-compile-schemas --strict schemas
fi
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share/gnome-shell/extensions/
cp -r -T . $out/share/gnome-shell/extensions/${uuid}
runHook postInstall
'';
meta = {
description = builtins.head (lib.splitString "\n" description);
longDescription = description;
homepage = link;
license = lib.licenses.gpl2Plus; # https://gjs.guide/extensions/review-guidelines/review-guidelines.html#licensing
platforms = lib.platforms.linux;
maintainers = [ lib.maintainers.honnip ];
};
passthru = {
extensionPortalSlug = pname;
# Store the extension's UUID, because we might need it at some places
extensionUuid = uuid;
tests = {
gnome-extensions = nixosTests.gnome-extensions;
};
};
};
in
lib.makeOverridable buildGnomeExtension

View File

@@ -0,0 +1,50 @@
{
lib,
stdenv,
fetchzip,
gnome-shell,
gettext,
glib,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-clock-override";
version = "12";
src = fetchzip {
url = "https://extensions.gnome.org/extension-data/clock-overridegnomeshell.kryogenix.org.v${version}.shell-extension.zip";
sha256 = "1cyaszks6bwnbgacqsl1pmr24mbj05mad59d4253la9am8ibb4m6";
stripRoot = false;
};
passthru = {
extensionUuid = "clock-override@gnomeshell.kryogenix.org";
extensionPortalSlug = "clock-override";
};
nativeBuildInputs = [
gettext
glib
];
buildPhase = ''
runHook preBuild
glib-compile-schemas --strict --targetdir=schemas schemas
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p "$out/share/gnome-shell/extensions/clock-override@gnomeshell.kryogenix.org"
cp -r {convenience.js,extension.js,format.js,locale,metadata.json,prefs.js,schemas} "$out/share/gnome-shell/extensions/clock-override@gnomeshell.kryogenix.org"
runHook postInstall
'';
meta = with lib; {
description = "Customize the date and time format displayed in clock in the top bar in GNOME Shell";
license = licenses.mit;
maintainers = with maintainers; [ rhoriguchi ];
homepage = "https://github.com/stuartlangridge/gnome-shell-clock-override";
broken = versionOlder gnome-shell.version "3.18";
};
}

View File

@@ -0,0 +1,43 @@
{
"applications-menu": [
"Applications_Menu@rmy.pobox.com",
"apps-menu@gnome-shell-extensions.gcampax.github.com"
],
"battery-time": [
"batime@martin.zurowietz.de",
"battery-time@eetumos.github.com",
"batterytime@typeof.pw"
],
"eur-usd": [
"eur-usd-gshell@vezza.github.com",
"usd-mxn-gshell@kinduff.github.com"
],
"fullscreen-to-empty-workspace": [
"fullscreen-to-empty-workspace2@corgijan.dev",
"fullscreen-to-empty-workspace@aiono.dev"
],
"fuzzy-clock": [
"FuzzyClock@fire-man-x",
"FuzzyClock@johngoetz"
],
"mouse-follows-focus": [
"mouse-follows-focus@crisidev.org",
"mousefollowsfocus@matthes.biz"
],
"nepali-calendar": [
"nepali-calendar-gs-extension@subashghimire.info.np",
"nepali-date@biplab"
],
"persian-calendar": [
"PersianCalendar@oxygenws.com",
"persian-calendar@iamrezamousavi.gmail.com"
],
"power-profile-indicator": [
"power-profile-indicator@laux.wtf",
"power-profile@fthx"
],
"system-monitor": [
"System_Monitor@bghome.gmail.com",
"system-monitor@gnome-shell-extensions.gcampax.github.com"
]
}

View File

@@ -0,0 +1,109 @@
{
lib,
callPackage,
config,
}:
let
buildShellExtension = callPackage ./buildGnomeExtension.nix { };
# Index of all scraped extensions (with supported versions)
extensionsIndex = lib.importJSON ./extensions.json;
# A list of UUIDs that have the same pname and we need to rename them
extensionRenames = import ./extensionRenames.nix;
# Take all extensions from the index that match the gnome version, build them and put them into a list of derivations
produceExtensionsList =
shell-version:
lib.trivial.pipe extensionsIndex [
# Does a given extension match our current shell version?
(builtins.filter (extension: (builtins.hasAttr shell-version extension."shell_version_map")))
# Take in an `extension` object from the JSON and transform it into the correct args to call `buildShellExtension`
(map (extension: {
inherit (extension)
uuid
name
description
link
pname
;
inherit (extension.shell_version_map.${shell-version}) version sha256 metadata;
}))
# Build them
(map buildShellExtension)
];
# Map the list of extensions to an attrset based on the UUID as key
mapUuidNames =
extensions:
lib.trivial.pipe extensions [
(map (extension: lib.nameValuePair extension.extensionUuid extension))
builtins.listToAttrs
];
# Map the list of extensions to an attrset based on the pname as key, which is more human readable than the UUID
# We also take care of conflict renaming in here
mapReadableNames =
extensionsList:
lib.trivial.pipe extensionsList [
# Filter out all extensions that map to null
(lib.filter (
extension:
!(
(builtins.hasAttr extension.extensionUuid extensionRenames)
&& ((builtins.getAttr extension.extensionUuid extensionRenames) == null)
)
))
# Map all extensions to their pname, with potential overwrites
(map (
extension:
lib.nameValuePair (extensionRenames.${extension.extensionUuid} or extension.extensionPortalSlug
) extension
))
builtins.listToAttrs
];
in
rec {
# Remember to import all these in all-packages.nix
gnome38Extensions = mapUuidNames (produceExtensionsList "38");
gnome40Extensions = mapUuidNames (produceExtensionsList "40");
gnome41Extensions = mapUuidNames (produceExtensionsList "41");
gnome42Extensions = mapUuidNames (produceExtensionsList "42");
gnome43Extensions = mapUuidNames (produceExtensionsList "43");
gnome44Extensions = mapUuidNames (produceExtensionsList "44");
gnome45Extensions = mapUuidNames (produceExtensionsList "45");
gnome46Extensions = mapUuidNames (produceExtensionsList "46");
gnome47Extensions = mapUuidNames (produceExtensionsList "47");
gnome48Extensions = mapUuidNames (produceExtensionsList "48");
# Keep the last three versions in here
gnomeExtensions = lib.trivial.pipe (gnome46Extensions // gnome47Extensions // gnome48Extensions) [
# Apply some custom patches for automatically packaged extensions
(callPackage ./extensionOverrides.nix { })
# Add all manually packaged extensions
(extensions: extensions // (import ./manuallyPackaged.nix { inherit callPackage; }))
# Map the extension UUIDs to readable names
(lib.attrValues)
mapReadableNames
# Add some aliases
(
extensions:
extensions
// lib.optionalAttrs config.allowAliases {
unite-shell = gnomeExtensions.unite; # added 2021-01-19
arc-menu = gnomeExtensions.arcmenu; # added 2021-02-14
icon-hider = throw "gnomeExtensions.icon-hider was removed on 2024-03-15. The extension has not received any updates since 2020/3.34.";
nohotcorner = throw "gnomeExtensions.nohotcorner removed since 2019-10-09: Since 3.34, it is a part of GNOME Shell configurable through GNOME Tweaks.";
mediaplayer = throw "gnomeExtensions.mediaplayer deprecated since 2019-09-23: retired upstream https://github.com/JasonLG1979/gnome-shell-extensions-mediaplayer/blob/master/README.md";
remove-dropdown-arrows = throw "gnomeExtensions.remove-dropdown-arrows removed since 2021-05-25: The extensions has not seen an update sine GNOME 3.34. Furthermore, the functionality it provides is obsolete as of GNOME 40.";
}
)
# Export buildShellExtension function
(extensions: extensions // { inherit buildShellExtension; })
# Make the set "public"
lib.recurseIntoAttrs
];
}

View File

@@ -0,0 +1,46 @@
{
lib,
stdenv,
fetchFromGitHub,
replaceVars,
gjs,
vte,
gnome,
}:
stdenv.mkDerivation {
pname = "gnome-shell-extension-drop-down-terminal";
version = "unstable-2020-03-25";
src = fetchFromGitHub {
owner = "zzrough";
repo = "gs-extensions-drop-down-terminal";
rev = "a59669afdb395b3315619f62c1f740f8b2f0690d";
sha256 = "0igfxgrjdqq6z6xg4rsawxn261pk25g5dw2pm3bhwz5sqsy4bq3i";
};
passthru = {
extensionUuid = "drop-down-terminal@gs-extensions.zzrough.org";
extensionPortalSlug = "drop-down-terminal";
};
patches = [
(replaceVars ./fix_vte_and_gjs.patch {
inherit gjs vte;
})
];
installPhase = ''
runHook preInstall
mkdir -p $out/share/gnome-shell/extensions
cp -r "drop-down-terminal@gs-extensions.zzrough.org" $out/share/gnome-shell/extensions/
runHook postInstall
'';
meta = with lib; {
description = "Configurable drop down terminal shell";
license = licenses.gpl3;
maintainers = with maintainers; [ ericdallo ];
homepage = "https://github.com/zzrough/gs-extensions-drop-down-terminal";
};
}

View File

@@ -0,0 +1,32 @@
--- a/drop-down-terminal@gs-extensions.zzrough.org/extension.js
+++ b/drop-down-terminal@gs-extensions.zzrough.org/extension.js
@@ -15,6 +15,8 @@
// Author: Stéphane Démurget <stephane.demurget@free.fr>
+imports.gi.GIRepository.Repository.prepend_search_path('@vte@/lib/girepository-1.0')
+
const Lang = imports.lang;
const Gettext = imports.gettext.domain("drop-down-terminal");
const Mainloop = imports.mainloop;
@@ -653,7 +655,7 @@ const DropDownTerminalExtension = new Lang.Class({
this._killingChild = false;
// finds the forking arguments
- let args = ["gjs", GLib.build_filenamev([Me.path, "terminal.js"]), Me.path];
+ let args = ["@gjs@/bin/gjs", GLib.build_filenamev([Me.path, "terminal.js"]), Me.path];
// forks the process
debug("forking '" + args.join(" ") + "'");
--- a/drop-down-terminal@gs-extensions.zzrough.org/terminal.js
+++ b/drop-down-terminal@gs-extensions.zzrough.org/terminal.js
@@ -14,6 +14,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Author: Stéphane Démurget <stephane.demurget@free.fr>
+
+imports.gi.GIRepository.Repository.prepend_search_path('@vte@/lib/girepository-1.0')
+
const Lang = imports.lang;
const Pango = imports.gi.Pango;

View File

@@ -0,0 +1,232 @@
{
lib,
fetchFromGitLab,
cpio,
ddcutil,
easyeffects,
gjs,
glib,
gnome-menus,
nautilus,
gobject-introspection,
hddtemp,
libgtop,
libhandy,
liquidctl,
lm_sensors,
netcat-gnu,
nvme-cli,
procps,
smartmontools,
replaceVars,
stdenvNoCC,
touchegg,
util-linux,
vte,
wrapGAppsHook3,
xdg-utils,
gtk4,
desktop-file-utils,
xdg-user-dirs,
}:
let
# Helper method to reduce redundancy
patchExtension =
name: override: super:
(
super
// {
${name} = super.${name}.overrideAttrs override;
}
);
in
# A set of overrides for automatically packaged extensions that require some small fixes.
# The input must be an attribute set with the extensions' UUIDs as keys and the extension
# derivations as values. Output is the same, but with patches applied.
#
# Note that all source patches refer to the built extension as published on extensions.gnome.org, and not
# the upstream repository's sources.
super:
lib.trivial.pipe super [
(patchExtension "apps-menu@gnome-shell-extensions.gcampax.github.com" (old: {
patches = [
(replaceVars
./extensionOverridesPatches/apps-menu_at_gnome-shell-extensions.gcampax.github.com.patch
{
gmenu_path = "${gnome-menus}/lib/girepository-1.0";
}
)
];
}))
(patchExtension "caffeine@patapon.info" (old: {
meta.maintainers = with lib.maintainers; [ eperuffo ];
}))
(patchExtension "dash-to-dock@micxgx.gmail.com" (old: {
meta.maintainers = with lib.maintainers; [ rhoriguchi ];
}))
(patchExtension "ddterm@amezin.github.com" (old: {
nativeBuildInputs = [
gobject-introspection
wrapGAppsHook3
];
buildInputs = [
vte
libhandy
gjs
];
postFixup = ''
patchShebangs "$out/share/gnome-shell/extensions/ddterm@amezin.github.com/bin/com.github.amezin.ddterm"
wrapGApp "$out/share/gnome-shell/extensions/ddterm@amezin.github.com/bin/com.github.amezin.ddterm"
'';
}))
(patchExtension "display-brightness-ddcutil@themightydeity.github.com" (old: {
# Make glib-compile-schemas available
nativeBuildInputs = [ glib ];
# Has a hard-coded path to a run-time dependency
# https://github.com/NixOS/nixpkgs/issues/136111
postPatch = ''
substituteInPlace "schemas/org.gnome.shell.extensions.display-brightness-ddcutil.gschema.xml" \
--replace-fail "/usr/bin/ddcutil" ${lib.getExe ddcutil}
'';
postFixup = ''
rm "$out/share/gnome-shell/extensions/display-brightness-ddcutil@themightydeity.github.com/schemas/gschemas.compiled"
glib-compile-schemas "$out/share/gnome-shell/extensions/display-brightness-ddcutil@themightydeity.github.com/schemas"
'';
}))
(patchExtension "eepresetselector@ulville.github.io" (old: {
patches = [
# Needed to find the currently set preset
(replaceVars ./extensionOverridesPatches/eepresetselector_at_ulville.github.io.patch {
easyeffects_gsettings_path = "${glib.getSchemaPath easyeffects}";
})
];
}))
(patchExtension "freon@UshakovVasilii_Github.yahoo.com" (old: {
patches = [
(replaceVars ./extensionOverridesPatches/freon_at_UshakovVasilii_Github.yahoo.com.patch {
inherit
hddtemp
liquidctl
lm_sensors
procps
smartmontools
;
netcat = netcat-gnu;
nvmecli = nvme-cli;
})
];
}))
(patchExtension "gnome-shell-screenshot@ttll.de" (old: {
# Requires gjs
# https://github.com/NixOS/nixpkgs/issues/136112
postPatch = ''
for file in *.js; do
substituteInPlace $file --replace "gjs" "${gjs}/bin/gjs"
done
'';
}))
(patchExtension "gtk4-ding@smedius.gitlab.com" (old: {
nativeBuildInputs = [ wrapGAppsHook3 ];
patches = [
(replaceVars ./extensionOverridesPatches/gtk4-ding_at_smedius.gitlab.com.patch {
inherit gjs;
util_linux = util-linux;
xdg_utils = xdg-utils;
gtk_update_icon_cache = "${gtk4.out}/bin/gtk4-update-icon-cache";
update_desktop_database = "${desktop-file-utils.out}/bin/update-desktop-database";
nautilus_gsettings_path = glib.getSchemaPath nautilus;
})
];
}))
(patchExtension "lunarcal@ailin.nemui" (
old:
let
chinese-calendar = stdenvNoCC.mkDerivation (finalAttrs: {
pname = "chinese-calendar";
version = "20240107";
nativeBuildInputs = [
cpio # used in install.sh
];
src = fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "Nei";
repo = "ChineseCalendar";
tag = finalAttrs.version;
hash = "sha256-z8Af9e70bn3ztUZteIEt/b3nJIFosbnoy8mwKMM6Dmc=";
};
installPhase = ''
runHook preInstall
HOME=$out ./install.sh
runHook postInstall
'';
});
in
{
patches = [
(replaceVars ./extensionOverridesPatches/lunarcal_at_ailin.nemui.patch {
chinese_calendar_path = chinese-calendar;
})
];
}
))
(patchExtension "system-monitor@gnome-shell-extensions.gcampax.github.com" (old: {
patches = [
(replaceVars
./extensionOverridesPatches/system-monitor_at_gnome-shell-extensions.gcampax.github.com.patch
{
gtop_path = "${libgtop}/lib/girepository-1.0";
}
)
];
}))
(patchExtension "system-monitor-next@paradoxxx.zero.gmail.com" (old: {
patches = [
(replaceVars ./extensionOverridesPatches/system-monitor-next_at_paradoxxx.zero.gmail.com.patch {
gtop_path = "${libgtop}/lib/girepository-1.0";
})
];
meta.maintainers = with lib.maintainers; [ andersk ];
}))
(patchExtension "Vitals@CoreCoding.com" (old: {
patches = [
(replaceVars ./extensionOverridesPatches/vitals_at_corecoding.com.patch {
gtop_path = "${libgtop}/lib/girepository-1.0";
})
];
}))
(patchExtension "x11gestures@joseexposito.github.io" (old: {
# Extension can't find Touchegg
# https://github.com/NixOS/nixpkgs/issues/137621
postPatch = ''
substituteInPlace "src/touchegg/ToucheggConfig.js" \
--replace "GLib.build_filenamev([GLib.DIR_SEPARATOR_S, 'usr', 'share', 'touchegg', 'touchegg.conf'])" "'${touchegg}/share/touchegg/touchegg.conf'"
'';
}))
(patchExtension "pwcalc@thilomaurer.de" {
postPatch = ''
# remove unused dangling symlink
rm settings-importexport.ui
'';
})
(patchExtension "TeaTimer@zener.sbg.at" {
postPatch = ''
# remove unused dangling symlink
rm utilities-teatime.svg
'';
})
]

View File

@@ -0,0 +1,17 @@
diff --git a/extension.js b/extension.js
index c608441..2b25335 100644
--- a/extension.js
+++ b/extension.js
@@ -9,7 +9,11 @@ import Atk from 'gi://Atk';
import Clutter from 'gi://Clutter';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
-import GMenu from 'gi://GMenu';
+
+import GIRepository from 'gi://GIRepository';
+GIRepository.Repository.prepend_search_path('@gmenu_path@');
+const {default: GMenu} = await import('gi://GMenu');
+
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
import Meta from 'gi://Meta';

View File

@@ -0,0 +1,28 @@
--- a/extension.js
+++ b/extension.js
@@ -397,9 +397,9 @@
// String (values are seperated by new line)
keys = listKeyResponse.trim().split('\n');
} else if (appType === 'native') {
- const settings = new Gio.Settings({
- schema_id: 'com.github.wwmm.easyeffects',
- });
+ const _schema_source = Gio.SettingsSchemaSource.new_from_directory('@easyeffects_gsettings_path@', Gio.SettingsSchemaSource.get_default(), true);
+ const _schema = _schema_source.lookup('com.github.wwmm.easyeffects', false);
+ const settings = new Gio.Settings({settings_schema: _schema});
keys = settings.settings_schema.list_keys();
}
// If key names are invalid, try fallback
@@ -432,9 +432,9 @@
_lastUsedInputPreset = _idata.trim().slice(1, -1);
} else if (appType === 'native') {
// Get last used presets
- const settings = new Gio.Settings({
- schema_id: 'com.github.wwmm.easyeffects',
- });
+ const _schema_source = Gio.SettingsSchemaSource.new_from_directory('@easyeffects_gsettings_path@', Gio.SettingsSchemaSource.get_default(), true);
+ const _schema = _schema_source.lookup('com.github.wwmm.easyeffects', false);
+ const settings = new Gio.Settings({settings_schema: _schema});
_lastUsedOutputPreset = settings.get_string(lastOutputKeyName);
_lastUsedInputPreset = settings.get_string(lastInputKeyName);
}

View File

@@ -0,0 +1,85 @@
diff --git a/hddtempUtil.js b/hddtempUtil.js
index e52fbc2..f5138bb 100644
--- a/hddtempUtil.js
+++ b/hddtempUtil.js
@@ -10,7 +10,7 @@ export default class HddtempUtil extends CommandLineUtil {
constructor() {
super();
- let hddtempArgv = GLib.find_program_in_path('hddtemp');
+ let hddtempArgv = '@hddtemp@/bin/hddtemp';
if(hddtempArgv) {
// check if this user can run hddtemp directly.
if(!GLib.spawn_command_line_sync(hddtempArgv)[3]){
@@ -22,8 +22,8 @@ export default class HddtempUtil extends CommandLineUtil {
// doesn't seem to be the case… is it running as a daemon?
// Check first for systemd
let systemctl = GLib.find_program_in_path('systemctl');
- let pidof = GLib.find_program_in_path('pidof');
- let nc = GLib.find_program_in_path('nc');
+ let pidof = '@procps@/bin/pidof';
+ let nc = '@netcat@/bin/nc';
let pid = undefined;
if(systemctl) {
@@ -38,7 +38,7 @@ export default class HddtempUtil extends CommandLineUtil {
// systemd isn't used on this system, try sysvinit instead
if(!pid && pidof) {
- let output = run_command("pidof hddtemp");
+ let output = run_command("@procps@/bin/pidof hddtemp");
if(output.length)
pid = Number(output.trim());
}
diff --git a/liquidctlUtil.js b/liquidctlUtil.js
index a2f3015..215707a 100644
--- a/liquidctlUtil.js
+++ b/liquidctlUtil.js
@@ -7,7 +7,7 @@ export default class LiquidctlUtil extends CommandLineUtil {
constructor() {
super();
- const path = GLib.find_program_in_path('liquidctl');
+ const path = '@liquidctl@/bin/liquidctl';
this._argv = path ? [path, 'status', '--json'] : null;
}
diff --git a/nvmecliUtil.js b/nvmecliUtil.js
index 2b12d2d..70609f7 100644
--- a/nvmecliUtil.js
+++ b/nvmecliUtil.js
@@ -1,7 +1,7 @@
import GLib from 'gi://GLib';
function getNvmeData (argv){
- const nvme = GLib.find_program_in_path('nvme')
+ const nvme = '@nvmecli@/bin/nvme'
return JSON.parse(new TextDecoder().decode(GLib.spawn_command_line_sync(`${nvme} ${argv} -o json`)[1]))
}
diff --git a/sensorsUtil.js b/sensorsUtil.js
index 90c6ca9..5788635 100644
--- a/sensorsUtil.js
+++ b/sensorsUtil.js
@@ -6,7 +6,7 @@ export default class SensorsUtil extends CommandLineUtil {
constructor() {
super();
- let path = GLib.find_program_in_path('sensors');
+ let path = '@lm_sensors@/bin/sensors';
// -A: Do not show adapter -j: JSON output
this._argv = path ? [path, '-A', '-j'] : null;
}
diff --git a/smartctlUtil.js b/smartctlUtil.js
index f58d194..b9cb9ca 100644
--- a/smartctlUtil.js
+++ b/smartctlUtil.js
@@ -1,7 +1,7 @@
import GLib from 'gi://GLib';
function getSmartData (argv){
- const smartctl = GLib.find_program_in_path('smartctl')
+ const smartctl = '@smartmontools@/bin/smartctl'
return JSON.parse(new TextDecoder().decode( GLib.spawn_command_line_sync(`'${smartctl}' ${argv} -j`)[1] ))
}

View File

@@ -0,0 +1,108 @@
diff --git a/app/adw-ding.js b/app/adw-ding.js
index 42cb878c..929ddce2 100755
--- a/app/adw-ding.js
+++ b/app/adw-ding.js
@@ -1,4 +1,4 @@
-#!/usr/bin/env -S gjs -m
+#!@gjs@/bin/gjs -m
/* ADW-DING: Desktop Icons New Generation for GNOME Shell
*
@@ -535,7 +535,7 @@ const adWDingApp = GObject.registerClass(
]);
const updated = await GLib.spawn_command_line_async(
- 'gtk-update-icon-cache ' +
+ '@gtk_update_icon_cache@ ' +
'-q -t -f ' +
`${iconCachePath}`
);
@@ -566,7 +566,7 @@ const adWDingApp = GObject.registerClass(
// and we need to do it manually for the app to be
// available sooner
const updated = await GLib.spawn_command_line_async(
- 'update-desktop-database -q ' +
+ '@update_desktop_database@ -q ' +
`${GLib.path_get_dirname(appDesktopFile)}`
);
diff --git a/app/enums.js b/app/enums.js
index 5434fa7a..e36d3670 100644
--- a/app/enums.js
+++ b/app/enums.js
@@ -134,7 +134,8 @@ export const THUMBNAILS_DIR = '.cache/thumbnails';
export const DND_HOVER_TIMEOUT = 1500; // In milliseconds
export const DND_SHELL_HOVER_POLL = 200; // In milliseconds
export const TOOLTIP_HOVER_TIMEOUT = 1000; // In milliseconds
-export const XDG_EMAIL_CMD = 'xdg-email';
+// Currently only used via https://gjs-docs.gnome.org/glib20~2.0/glib.find_program_in_path so using an absolute path is fine
+export const XDG_EMAIL_CMD = '@xdg_utils@/bin/xdg-email';
export const XDG_EMAIL_CMD_OPTIONS = '--attach';
export const ZIP_CMD = 'zip';
export const ZIP_CMD_OPTIONS = '-r';
diff --git a/app/preferences.js b/app/preferences.js
index 95ffe60b..75370403 100644
--- a/app/preferences.js
+++ b/app/preferences.js
@@ -30,6 +30,7 @@ const Preferences = class {
this._mainApp = Data.mainApp;
this._Enums = Data.Enums;
let schemaSource = GioSSS.get_default();
+ const schemaSourceNautilus = Gio.SettingsSchemaSource.new_from_directory('@nautilus_gsettings_path@', Gio.SettingsSchemaSource.get_default(), true);
this._desktopManager = null;
// Adw Style Manager
@@ -52,7 +53,7 @@ const Preferences = class {
// Gnome Files
const schemaObj =
- schemaSource.lookup(this._Enums.SCHEMA_NAUTILUS, true);
+ schemaSourceNautilus.lookup(this._Enums.SCHEMA_NAUTILUS, true);
if (!schemaObj) {
this.nautilusSettings = null;
@@ -69,7 +70,7 @@ const Preferences = class {
// Compression
const compressionSchema =
- schemaSource.lookup(this._Enums.SCHEMA_NAUTILUS_COMPRESSION, true);
+ schemaSourceNautilus.lookup(this._Enums.SCHEMA_NAUTILUS_COMPRESSION, true);
if (!compressionSchema) {
this.nautilusCompression = null;
diff --git a/dingManager.js b/dingManager.js
index 7a0de9e3..bbc23704 100644
--- a/dingManager.js
+++ b/dingManager.js
@@ -482,7 +482,7 @@ const DingManager = class {
async _doKillAllOldDesktopProcesses() {
const procFolder = Gio.File.new_for_path('/proc');
const processes = await FileUtils.enumerateDir(procFolder);
- const thisPath = `gjs ${GLib.build_filenamev([
+ const thisPath = `@gjs@/bin/gjs ${GLib.build_filenamev([
this.path,
'app',
'adw-ding.js',
@@ -510,7 +510,7 @@ const DingManager = class {
if (contents.startsWith(thisPath)) {
let proc =
- new Gio.Subprocess({argv: ['/bin/kill', filename]});
+ new Gio.Subprocess({argv: ['@util_linux@/bin/kill', filename]});
proc.init(null);
console.log(`Killing old DING process ${filename}`);
diff --git a/prefs.js b/prefs.js
index 50430fa5..82fca2e3 100644
--- a/prefs.js
+++ b/prefs.js
@@ -34,7 +34,8 @@ export default class dingPreferences extends ExtensionPreferences {
const schemaSource = GioSSS.get_default();
const schemaGtk = schemaSource.lookup(Enums.SCHEMA_GTK, true);
const gtkSettings = new Gio.Settings({settings_schema: schemaGtk});
- const schemaNautilus = schemaSource.lookup(Enums.SCHEMA_NAUTILUS, true);
+ const schemaSourceNautilus = Gio.SettingsSchemaSource.new_from_directory('@nautilus_gsettings_path@', Gio.SettingsSchemaSource.get_default(), true);
+ const schemaNautilus = schemaSourceNautilus.lookup(Enums.SCHEMA_NAUTILUS, true);
const version = this.metadata['version-name'];
let nautilusSettings;

View File

@@ -0,0 +1,31 @@
diff --git a/backend/ytliu0-loader.js b/backend/ytliu0-loader.js
index 4862c17..25fe9e8 100644
--- a/backend/ytliu0-loader.js
+++ b/backend/ytliu0-loader.js
@@ -8,7 +8,11 @@ import GLib from 'gi://GLib'
// Code from gnome-shell 44 : extenstionUtils.js:installImporter
let custom_importer
const origSearchPath = imports.searchPath.slice()
-imports.searchPath = [GLib.get_user_data_dir(), ...GLib.get_system_data_dirs()]
+imports.searchPath = [
+ GLib.get_user_data_dir(),
+ ...GLib.get_system_data_dirs(),
+ '@chinese_calendar_path@/.local/share'
+]
try {
// importing a "subdir" creates a new importer object that doesn't affect
// the global one
diff --git a/backend/ytliu0.js b/backend/ytliu0.js
index 94abd2c..df6241b 100644
--- a/backend/ytliu0.js
+++ b/backend/ytliu0.js
@@ -60,7 +60,8 @@ class LunarDateX {
const [ok, file] = this._holidayData.load_from_dirs(holiday_fn, [
GLib.get_user_config_dir(),
GLib.get_user_data_dir(),
- ...GLib.get_system_data_dirs()
+ ...GLib.get_system_data_dirs(),
+ '@chinese_calendar_path@/.config'
], GLib.KeyFileFlags.KEEP_TRANSLATIONS)
if (this._notifyHoliday)
this._notifyHoliday()

View File

@@ -0,0 +1,30 @@
diff --git a/extension.js b/extension.js
index ee8c3a9..ca72885 100644
--- a/extension.js
+++ b/extension.js
@@ -21,6 +21,7 @@
import { Extension, gettext as _ } from "resource:///org/gnome/shell/extensions/extension.js";
import Clutter from "gi://Clutter";
+import GIRepository from "gi://GIRepository";
import GLib from "gi://GLib";
import GObject from "gi://GObject";
@@ -28,7 +29,6 @@ import Gio from "gi://Gio";
import Shell from "gi://Shell";
import St from "gi://St";
import UPowerGlib from "gi://UPowerGlib";
-import GTop from "gi://GTop";
import NM from "gi://NM";
import * as ModalDialog from "resource:///org/gnome/shell/ui/modalDialog.js";
@@ -41,6 +41,9 @@ import * as PopupMenu from "resource:///org/gnome/shell/ui/popupMenu.js";
import * as Util from "resource:///org/gnome/shell/misc/util.js";
+GIRepository.Repository.prepend_search_path('@gtop_path@');
+const GTop = (await import("gi://GTop")).default;
+
const NetworkManager = NM;
const UPower = UPowerGlib;
// Copied as of https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/5fa08fe53376f5dca755360bd005a4a51ca78917/js/ui/panel.js#L45

View File

@@ -0,0 +1,25 @@
diff --git a/extension.js b/extension.js
index 37d2eb1..232d0d5 100644
--- a/extension.js
+++ b/extension.js
@@ -6,9 +6,9 @@
import Clutter from 'gi://Clutter';
import Gio from 'gi://Gio';
+import GIRepository from "gi://GIRepository";
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
-import GTop from 'gi://GTop';
import Pango from 'gi://Pango';
import Shell from 'gi://Shell';
import St from 'gi://St';
@@ -19,6 +19,9 @@ import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+GIRepository.Repository.prepend_search_path('@gtop_path@');
+const GTop = (await import("gi://GTop")).default;
+
const THRESHOLD_HIGH = 0.80;
// adapted from load-graph.cpp in gnome-system-monitor

View File

@@ -0,0 +1,13 @@
diff --git a/sensors.js b/sensors.js
index 39d175a..9815b77 100644
--- a/sensors.js
+++ b/sensors.js
@@ -29,6 +29,8 @@ import * as FileModule from './helpers/file.js';
import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js';
import NM from 'gi://NM';
+imports.gi.GIRepository.Repository.prepend_search_path('@gtop_path@');
+
let GTop, hasGTop = true;
try {
({default: GTop} = await import('gi://GTop'));

View File

@@ -0,0 +1,60 @@
# A list of UUIDs that have the same pname and we need to rename them
# MAINTENANCE:
# - Every item from ./collisions.json (for the respective Shell version) should have an entry in here
# - Set the value to `null` for filtering (duplicate or unmaintained extensions)
# - Sort the entries in order of appearance in the collisions.json
{
"Applications_Menu@rmy.pobox.com" = "frippery-applications-menu";
"apps-menu@gnome-shell-extensions.gcampax.github.com" = "applications-menu";
"persian-calendar@iamrezamousavi.gmail.com" = "persian-calendar-2";
"PersianCalendar@oxygenws.com" = "persian-calendar";
"system-monitor@gnome-shell-extensions.gcampax.github.com" = "system-monitor";
"System_Monitor@bghome.gmail.com" = "system-monitor-2";
"FuzzyClock@fire-man-x" = "fuzzy-clock-3";
"FuzzyClock@johngoetz" = "fuzzy-clock";
"battery-time@eetumos.github.com" = "battery-time-3";
"batterytime@typeof.pw" = "battery-time-2";
"batime@martin.zurowietz.de" = "battery-time";
"nepali-date@biplab" = "nepali-calendar";
"nepali-calendar-gs-extension@subashghimire.info.np" = "nepali-calendar-2";
"mousefollowsfocus@matthes.biz" = "mouse-follows-focus";
"mouse-follows-focus@crisidev.org" = "mouse-follows-focus-2";
"power-profile-indicator@laux.wtf" = "power-profile-indicator";
"power-profile@fthx" = "power-profile-indicator-2";
"fullscreen-to-empty-workspace@aiono.dev" = "fullscreen-to-empty-workspace";
"fullscreen-to-empty-workspace2@corgijan.dev" = "fullscreen-to-empty-workspace-2";
"eur-usd-gshell@vezza.github.com" = "eur-usd";
"usd-mxn-gshell@kinduff.github.com" = "usd-mxn";
# ############################################################################
# These extensions no longer collide. We preserve the old attribute name for backwards compatibility.
"floatingDock@sun.wxg@gmail.com" = "floating-dock-2";
"true-color-window-invert@lynet101" = "true-color-window-invert";
"volume_scroller@francislavoie.github.io" = "volume-scroller-2";
"openweather-extension@penguin-teal.github.io" = "openweather-refined";
# ############################################################################
# Overrides for extensions that were manually packaged in the past but are gradually
# being replaced by automatic packaging where possible.
#
# The manually packaged ones:
"EasyScreenCast@iacopodeenosee.gmail.com" = "easyScreenCast"; # extensionPortalSlug is "easyscreencast"
"gnome-fuzzy-app-search@gnome-shell-extensions.Czarlie.gitlab.com" = "fuzzy-app-search"; # extensionPortalSlug is "gnome-fuzzy-app-search"
"TopIcons@phocean.net" = "topicons-plus"; # extensionPortalSlug is "topicons"
"no-title-bar@jonaspoehler.de" = "no-title-bar"; # extensionPortalSlug is "no-title-bar-forked"
# These extensions are automatically packaged at the moment. We preserve the old attribute name
# for backwards compatibility.
"appindicatorsupport@rgcjonas.gmail.com" = "appindicator"; # extensionPortalSlug is "appindicator-support"
"drawOnYourScreen@abakkk.framagit.org" = "draw-on-your-screen"; # extensionPortalSlug is "draw-on-you-screen"
"timepp@zagortenay333" = "timepp"; # extensionPortalSlug is "time"
"windowIsReady_Remover@nunofarruca@gmail.com" = "window-is-ready-remover"; # extensionPortalSlug is "window-is-ready-notification-remover"
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,128 @@
{
stdenv,
lib,
fetchFromGitHub,
replaceVars,
openssl,
gsound,
meson,
ninja,
pkg-config,
gobject-introspection,
wrapGAppsHook3,
glib,
glib-networking,
gtk3,
openssh,
gnome-shell,
evolution-data-server-gtk4,
gjs,
nixosTests,
desktop-file-utils,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "gnome-shell-extension-gsconnect";
version = "66";
outputs = [
"out"
"installedTests"
];
src = fetchFromGitHub {
owner = "GSConnect";
repo = "gnome-shell-extension-gsconnect";
rev = "v${finalAttrs.version}";
hash = "sha256-QPvdSmt4aUkPvaOUonovrCxW4pxrgoopXGi3KSukVD8=";
};
patches = [
# Make typelibs available in the extension
(replaceVars ./fix-paths.patch {
gapplication = "${glib.bin}/bin/gapplication";
# Replaced in postPatch
typelibPath = null;
})
# Allow installing installed tests to a separate output
./installed-tests-path.patch
];
nativeBuildInputs = [
meson
ninja
pkg-config
gobject-introspection # for locating typelibs
wrapGAppsHook3 # for wrapping daemons
desktop-file-utils # update-desktop-database
];
buildInputs = [
glib # libgobject
glib-networking
gtk3
gsound
gjs # for running daemon
evolution-data-server-gtk4 # for libebook-contacts typelib
];
mesonFlags = [
"-Dgnome_shell_libdir=${gnome-shell}/lib"
"-Dchrome_nmhdir=${placeholder "out"}/etc/opt/chrome/native-messaging-hosts"
"-Dchromium_nmhdir=${placeholder "out"}/etc/chromium/native-messaging-hosts"
"-Dopenssl_path=${openssl}/bin/openssl"
"-Dsshadd_path=${openssh}/bin/ssh-add"
"-Dsshkeygen_path=${openssh}/bin/ssh-keygen"
"-Dsession_bus_services_dir=${placeholder "out"}/share/dbus-1/services"
"-Dinstalled_test_prefix=${placeholder "installedTests"}"
];
postPatch = ''
patchShebangs installed-tests/prepare-tests.sh
# TODO: do not include every typelib everywhere
# for example, we definitely do not need nautilus
substituteInPlace src/__nix-prepend-search-paths.js \
--subst-var-by typelibPath "$GI_TYPELIB_PATH"
# slightly janky fix for gsettings_schemadir being removed
substituteInPlace data/config.js.in \
--subst-var-by GSETTINGS_SCHEMA_DIR \
${glib.makeSchemaPath (placeholder "out") "${finalAttrs.pname}-${finalAttrs.version}"}
'';
postFixup = ''
# Lets wrap the daemons
for file in $out/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/{daemon,nativeMessagingHost}.js; do
echo "Wrapping program $file"
wrapGApp "$file"
done
# Wrap jasmine runner for tests
for file in $installedTests/libexec/installed-tests/gsconnect/minijasmine; do
echo "Wrapping program $file"
wrapGApp "$file"
done
'';
passthru = {
extensionUuid = "gsconnect@andyholmes.github.io";
extensionPortalSlug = "gsconnect";
};
passthru = {
tests = {
installedTests = nixosTests.installed-tests.gsconnect;
};
};
meta = {
description = "KDE Connect implementation for Gnome Shell";
homepage = "https://github.com/GSConnect/gnome-shell-extension-gsconnect/wiki";
license = lib.licenses.gpl2Plus;
maintainers = with lib.maintainers; [ doronbehar ];
teams = [ lib.teams.gnome ];
platforms = lib.platforms.linux;
};
})

View File

@@ -0,0 +1,60 @@
diff --git a/data/org.gnome.Shell.Extensions.GSConnect.desktop.in b/data/org.gnome.Shell.Extensions.GSConnect.desktop.in
index 3fb887c3..e8cbe1bd 100644
--- a/data/org.gnome.Shell.Extensions.GSConnect.desktop.in
+++ b/data/org.gnome.Shell.Extensions.GSConnect.desktop.in
@@ -5,7 +5,7 @@
[Desktop Entry]
Type=Application
Name=GSConnect
-Exec=gapplication launch org.gnome.Shell.Extensions.GSConnect %U
+Exec=@gapplication@ launch org.gnome.Shell.Extensions.GSConnect %U
Terminal=false
NoDisplay=true
Icon=org.gnome.Shell.Extensions.GSConnect
diff --git a/src/__nix-prepend-search-paths.js b/src/__nix-prepend-search-paths.js
new file mode 100644
index 00000000..d009dfd9
--- /dev/null
+++ b/src/__nix-prepend-search-paths.js
@@ -0,0 +1,2 @@
+import GIRepository from 'gi://GIRepository';
+'@typelibPath@'.split(':').forEach(path => GIRepository.Repository.prepend_search_path(path));
diff --git a/src/extension.js b/src/extension.js
index 53ecd5fc..78782357 100644
--- a/src/extension.js
+++ b/src/extension.js
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+import './__nix-prepend-search-paths.js';
+
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
diff --git i/src/gsconnect-preferences w/src/gsconnect-preferences
index b16ddc7d..263dfb04 100755
--- a/src/gsconnect-preferences
+++ b/src/gsconnect-preferences
@@ -6,6 +6,8 @@
// -*- mode: js; -*-
+import './__nix-prepend-search-paths.js';
+
import Gdk from 'gi://Gdk?version=3.0';
import 'gi://GdkPixbuf?version=2.0';
import Gio from 'gi://Gio?version=2.0';
diff --git a/src/prefs.js b/src/prefs.js
index dd20fd20..5f82c53a 100644
--- a/src/prefs.js
+++ b/src/prefs.js
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+import './__nix-prepend-search-paths.js';
+
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import Adw from 'gi://Adw';

View File

@@ -0,0 +1,33 @@
diff --git a/installed-tests/meson.build b/installed-tests/meson.build
index 5bc38bfd..02404c3a 100644
--- a/installed-tests/meson.build
+++ b/installed-tests/meson.build
@@ -2,8 +2,8 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
-installed_tests_execdir = join_paths(libexecdir, 'installed-tests', meson.project_name())
-installed_tests_metadir = join_paths(datadir, 'installed-tests', meson.project_name())
+installed_tests_execdir = join_paths(get_option('installed_test_prefix'), 'libexec', 'installed-tests', meson.project_name())
+installed_tests_metadir = join_paths(get_option('installed_test_prefix'), 'share', 'installed-tests', meson.project_name())
installed_tests_srcdir = meson.current_source_dir()
installed_tests_builddir = meson.current_build_dir()
diff --git a/meson_options.txt b/meson_options.txt
index 745c541c..b4b602ca 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -104,6 +104,13 @@ option(
description: 'Native Messaging Host directory for Mozilla'
)
+option(
+ 'installed_test_prefix',
+ type: 'string',
+ value: '',
+ description: 'Prefix for installed tests'
+)
+
option(
'installed_tests',
type: 'boolean',

View File

@@ -0,0 +1,55 @@
{
stdenv,
lib,
fetchFromGitLab,
glib,
}:
# We package this manually because upstream stopped updating the package to
# extensions.gnome.org. See:
# https://gitlab.com/ente76/guillotine/-/issues/17
stdenv.mkDerivation (finalAttrs: {
pname = "gnome-shell-extension-guillotine";
version = "26";
src = fetchFromGitLab {
owner = "ente76";
repo = "guillotine";
rev = "v${finalAttrs.version}";
hash = "sha256-6RuHargk7sq6oUKj+aGPFp3t0LJCpj6RwLhNzAM5wVA=";
};
nativeBuildInputs = [ glib ];
passthru = {
extensionUuid = "guillotine@fopdoodle.net";
extensionPortalSlug = "guillotine";
};
buildPhase = ''
runHook preBuild
rm schemas/gschemas.compiled
glib-compile-schemas schemas
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share/gnome-shell/extensions/guillotine@fopdoodle.net
cp -R schemas "$out/share/gnome-shell/extensions/guillotine@fopdoodle.net"
cp default.json $out/share/gnome-shell/extensions/guillotine@fopdoodle.net
cp extension.js "$out/share/gnome-shell/extensions/guillotine@fopdoodle.net"
cp guillotine-symbolic.svg "$out/share/gnome-shell/extensions/guillotine@fopdoodle.net"
cp LICENSE "$out/share/gnome-shell/extensions/guillotine@fopdoodle.net"
cp metadata.json "$out/share/gnome-shell/extensions/guillotine@fopdoodle.net"
cp README.md "$out/share/gnome-shell/extensions/guillotine@fopdoodle.net"
runHook postInstall
'';
meta = {
description = "Gnome extension designed for efficiently carrying out executions of commands from a customizable menu";
homepage = "https://gitlab.com/ente76/guillotine/";
license = lib.licenses.gpl3Plus;
maintainers = with lib.maintainers; [ husky ];
platforms = lib.platforms.linux;
};
})

View File

@@ -0,0 +1,39 @@
{
lib,
stdenv,
fetchFromGitHub,
gnome-shell,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-icon-hider";
version = "23";
src = fetchFromGitHub {
owner = "ikalnytskyi";
repo = "gnome-shell-extension-icon-hider";
rev = "v${version}";
sha256 = "18c8zkdrmdbghqqz7b450vhgpykgz25mgigwn2nggcb2lxmvm9ks";
};
passthru = {
extensionUuid = "icon-hider@kalnitsky.org";
extensionPortalSlug = "icon-hider";
};
installPhase = ''
runHook preInstall
mkdir -p $out/share/gnome-shell/extensions
cp -r "icon-hider@kalnitsky.org" $out/share/gnome-shell/extensions
runHook postInstall
'';
meta = with lib; {
description = "Icon Hider is a GNOME Shell extension for managing status area items";
license = licenses.bsd3;
maintainers = [ ];
platforms = gnome-shell.meta.platforms;
homepage = "https://github.com/ikalnytskyi/gnome-shell-extension-icon-hider";
broken = versionAtLeast gnome-shell.version "3.32"; # Doesn't support 3.34
};
}

View File

@@ -0,0 +1,50 @@
{
lib,
stdenv,
fetchFromGitHub,
glib,
}:
stdenv.mkDerivation {
pname = "gnome-shell-extension-impatience";
version = "0.5.2-unstable-2025-02-24";
src = fetchFromGitHub {
owner = "timbertson";
repo = "gnome-shell-impatience";
rev = "527295a35b352596fed1fc07799f1e0792a77040"; # shows gnome 48 support
hash = "sha256-9xfZcKJpBttSP2IbGtjo4UxFEnADgQjyV3vx0jSg8nI=";
};
buildInputs = [
glib
];
buildPhase = ''
runHook preBuild
make schemas
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share/gnome-shell/extensions
cp -r impatience "$out/share/gnome-shell/extensions/impatience@gfxmonk.net"
runHook postInstall
'';
passthru = {
extensionUuid = "impatience@gfxmonk.net";
extensionPortalSlug = "impatience";
};
meta = with lib; {
description = "Speed up builtin gnome-shell animations";
license = licenses.gpl3Plus;
maintainers = with maintainers; [
timbertson
tiramiseb
];
homepage = "http://gfxmonk.net/dist/0install/gnome-shell-impatience.xml";
};
}

View File

@@ -0,0 +1,25 @@
{ callPackage }:
{
"arcmenu@arcmenu.com" = callPackage ./arcmenu { };
"argos@pew.worldwidemann.com" = callPackage ./argos { };
"clock-override@gnomeshell.kryogenix.org" = callPackage ./clock-override { };
"drop-down-terminal@gs-extensions.zzrough.org" = callPackage ./drop-down-terminal { };
"EasyScreenCast@iacopodeenosee.gmail.com" = callPackage ./EasyScreenCast { };
"gsconnect@andyholmes.github.io" = callPackage ./gsconnect { };
"guillotine@fopdoodle.net" = callPackage ./guillotine { };
"impatience@gfxmonk.net" = callPackage ./impatience { };
"no-title-bar@jonaspoehler.de" = callPackage ./no-title-bar { };
"pidgin@muffinmad" = callPackage ./pidgin-im-integration { };
"pop-shell@system76.com" = callPackage ./pop-shell { };
"sound-output-device-chooser@kgshank.net" = callPackage ./sound-output-device-chooser { };
"systemd-manager@hardpixel.eu" = callPackage ./systemd-manager { };
"taskwhisperer-extension@infinicode.de" = callPackage ./taskwhisperer { };
"tilingnome@rliang.github.com" = callPackage ./tilingnome { };
"TopIcons@phocean.net" = callPackage ./topicons-plus { };
# Can be removed when https://github.com/hardpixel/unite-shell/issues/353 resolved
"unite@hardpixel.eu" = callPackage ./unite { };
"valent@andyholmes.ca" = callPackage ./valent { };
"window-corner-preview@fabiomereu.it" = callPackage ./window-corner-preview { };
# Can be removed when https://github.com/oae/gnome-shell-pano/issues/271 resolved
"pano@elhan.io" = callPackage ./pano { };
}

View File

@@ -0,0 +1,47 @@
{
lib,
stdenv,
fetchFromGitHub,
replaceVars,
glib,
gettext,
xorg,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-no-title-bar";
version = "11";
src = fetchFromGitHub {
owner = "poehlerj";
repo = "no-title-bar";
rev = "V_${version}";
sha256 = "07ddw47binlsbyvgy4xkdjvd40zyp7nwd17r6k7w54d50vmnwhvb";
};
nativeBuildInputs = [
glib
gettext
];
patches = [
(replaceVars ./fix-paths.patch {
xprop = "${xorg.xprop}/bin/xprop";
xwininfo = "${xorg.xwininfo}/bin/xwininfo";
})
];
makeFlags = [ "INSTALLBASE=$(out)/share/gnome-shell/extensions" ];
passthru = {
extensionUuid = "no-title-bar@jonaspoehler.de";
};
meta = with lib; {
description = "Integrates maximized windows with the top panel";
homepage = "https://github.com/poehlerj/no-title-bar";
license = licenses.gpl2;
maintainers = with maintainers; [ svsdep ];
platforms = platforms.linux;
};
}

View File

@@ -0,0 +1,56 @@
diff --git a/decoration.js b/decoration.js
index d1ff3dd..ff4193f 100644
--- a/decoration.js
+++ b/decoration.js
@@ -223,7 +223,7 @@ var Decoration = class {
let winId = this._guessWindowXID(win);
- let xprops = GLib.spawn_command_line_sync(`xprop -id ${winId}`);
+ let xprops = GLib.spawn_command_line_sync(`@xprop@ -id ${winId}`);
if (!xprops[0]) {
Utils.log_debug(`Unable to determine windows '${win.get_title()}' original state`);
return win._noTitleBarOriginalState = WindowState.UNKNOWN;
@@ -237,7 +237,7 @@ var Decoration = class {
let prop = '_MOTIF_WM_HINTS';
let value = '0x2, 0x0, %s, 0x0, 0x0'.format(hide ? '0x2' : '0x1');
- GLib.spawn_command_line_sync(`xprop -id ${windId} -f ${prop} 32c -set ${prop} "${value}"`);
+ GLib.spawn_command_line_sync(`@xprop@ -id ${windId} -f ${prop} 32c -set ${prop} "${value}"`);
if (!hide && !win.titlebar_is_onscreen()) {
Utils.log_debug(`Shoving titlebar onscreen for window '${win.get_title()}'`);
win.shove_titlebar_onscreen();
@@ -354,7 +354,7 @@ var Decoration = class {
let act = win.get_compositor_private();
let xwindow = act && act['x-window'];
if (xwindow) {
- let xwininfo = GLib.spawn_command_line_sync('xwininfo -children -id 0x%x'.format(xwindow));
+ let xwininfo = GLib.spawn_command_line_sync('@xwininfo@ -children -id 0x%x'.format(xwindow));
if (xwininfo[0]) {
let str = ByteArray.toString(xwininfo[1]);
@@ -384,7 +384,7 @@ var Decoration = class {
// Try enumerating all available windows and match the title. Note that this
// may be necessary if the title contains special characters and `x-window`
// is not available.
- let result = GLib.spawn_command_line_sync('xprop -root _NET_CLIENT_LIST');
+ let result = GLib.spawn_command_line_sync('@xprop@ -root _NET_CLIENT_LIST');
if (result[0]) {
let str = ByteArray.toString(result[1]);
@@ -395,7 +395,7 @@ var Decoration = class {
// For each window ID, check if the title matches the desired title.
for (var i = 0; i < windowList.length; ++i) {
- let cmd = 'xprop -id "' + windowList[i] + '" _NET_WM_NAME _NO_TITLE_BAR_ORIGINAL_STATE';
+ let cmd = '@xprop@ -id "' + windowList[i] + '" _NET_WM_NAME _NO_TITLE_BAR_ORIGINAL_STATE';
let result = GLib.spawn_command_line_sync(cmd);
if (result[0]) {
@@ -455,4 +455,4 @@ var Decoration = class {
let styleContent = this._updateUserStyles();
GLib.file_set_contents(this._userStylesPath, styleContent);
}
-}
\ No newline at end of file
+}

View File

@@ -0,0 +1,55 @@
{
lib,
stdenv,
fetchzip,
glib,
libgda6,
gsound,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "gnome-shell-extension-pano";
version = "23-alpha5";
src = fetchzip {
url = "https://github.com/oae/gnome-shell-pano/releases/download/v${finalAttrs.version}/pano@elhan.io.zip";
hash = "sha256-kTaJOSyFtBa/fl3Mot8Q8qyhwJwhcbBY4FvdztqUP4w=";
stripRoot = false;
};
nativeBuildInputs = [
glib
];
buildPhase = ''
runHook preBuild
glib-compile-schemas --strict schemas
runHook postBuild
'';
preInstall = ''
substituteInPlace extension.js \
--replace-fail "import Gda from 'gi://Gda?version>=5.0'" "imports.gi.GIRepository.Repository.prepend_search_path('${libgda6}/lib/girepository-1.0'); const Gda = (await import('gi://Gda')).default" \
--replace-fail "import GSound from 'gi://GSound'" "imports.gi.GIRepository.Repository.prepend_search_path('${gsound}/lib/girepository-1.0'); const GSound = (await import('gi://GSound')).default"
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share/gnome-shell/extensions
cp -r -T . $out/share/gnome-shell/extensions/pano@elhan.io
runHook postInstall
'';
passthru = {
extensionPortalSlug = "pano";
extensionUuid = "pano@elhan.io";
};
meta = with lib; {
description = "Next-gen Clipboard Manager for Gnome Shell";
homepage = "https://github.com/oae/gnome-shell-pano";
license = licenses.gpl2Plus;
maintainers = with maintainers; [ honnip ];
platforms = platforms.linux;
};
})

View File

@@ -0,0 +1,45 @@
{
lib,
stdenv,
fetchFromGitHub,
glib,
gnome-shell,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-pidgin-im-integration";
version = "32";
src = fetchFromGitHub {
owner = "muffinmad";
repo = "pidgin-im-gnome-shell-extension";
rev = "v${version}";
sha256 = "1jyg8r0s1v83sgg6y0jbsj2v37mglh8rvd8vi27fxnjq9xmg8kpc";
};
dontConfigure = true;
dontBuild = true;
installPhase = ''
runHook preInstall
share_dir="$prefix/share"
extensions_dir="$share_dir/gnome-shell/extensions/pidgin@muffinmad"
mkdir -p "$extensions_dir"
mv *.js metadata.json dbus.xml schemas locale "$extensions_dir"
runHook postInstall
'';
passthru = {
extensionUuid = "pidgin@muffinmad";
extensionPortalSlug = "pidgin-im-integration";
};
meta = with lib; {
homepage = "https://github.com/muffinmad/pidgin-im-gnome-shell-extension";
description = "Make Pidgin IM conversations appear in the Gnome Shell message tray";
license = licenses.gpl2;
platforms = platforms.linux;
maintainers = [ ];
broken = versionAtLeast gnome-shell.version "3.32"; # Doesn't support 3.34
};
}

View File

@@ -0,0 +1,59 @@
{
stdenv,
lib,
fetchFromGitHub,
glib,
gjs,
typescript,
unstableGitUpdater,
}:
stdenv.mkDerivation {
pname = "gnome-shell-extension-pop-shell";
version = "1.2.0-unstable-2025-07-09";
src = fetchFromGitHub {
owner = "pop-os";
repo = "shell";
rev = "6fd8c039a081e8ad7bbd40ef7883ec6e5fc2a3f8";
hash = "sha256-3zIbfjaJSUbPmUVppoSBWviQWQvykaT1qw9uQvcXmvM=";
};
nativeBuildInputs = [
glib
gjs
typescript
];
buildInputs = [ gjs ];
patches = [
./fix-gjs.patch
];
makeFlags = [ "XDG_DATA_HOME=$(out)/share" ];
passthru = {
extensionUuid = "pop-shell@system76.com";
extensionPortalSlug = "pop-shell";
updateScript = unstableGitUpdater { };
};
postPatch = ''
for file in */main.js; do
substituteInPlace $file --replace "gjs" "${gjs}/bin/gjs"
done
'';
preFixup = ''
chmod +x $out/share/gnome-shell/extensions/pop-shell@system76.com/*/main.js
'';
meta = with lib; {
description = "Keyboard-driven layer for GNOME Shell";
license = licenses.gpl3Only;
platforms = platforms.linux;
maintainers = [ maintainers.genofire ];
homepage = "https://github.com/pop-os/shell";
};
}

View File

@@ -0,0 +1,38 @@
diff --git a/src/extension.ts b/src/extension.ts
index f34e865..f12d4db 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -556,7 +556,7 @@ export class Ext extends Ecs.System<ExtEvent> {
return true;
};
- const ipc = utils.async_process_ipc(['gjs', '--module', path]);
+ const ipc = utils.async_process_ipc([path]);
if (ipc) {
const generator = (stdout: any, res: any) => {
diff --git a/src/panel_settings.ts b/src/panel_settings.ts
index fbcafbf..ef409ee 100644
--- a/src/panel_settings.ts
+++ b/src/panel_settings.ts
@@ -352,7 +352,7 @@ function color_selector(ext: Ext, menu: any) {
color_selector_item.add_child(color_button);
color_button.connect('button-press-event', () => {
let path = get_current_path() + '/color_dialog/main.js';
- let resp = GLib.spawn_command_line_async(`gjs --module ${path}`);
+ let resp = GLib.spawn_command_line_async(`${path}`);
if (!resp) {
return null;
}
diff --git a/src/color_dialog/src/main.ts b/src/color_dialog/src/main.ts
index a9637e5..5cb86ce 100644
--- a/src/color_dialog/src/main.ts
+++ b/src/color_dialog/src/main.ts
@@ -6,6 +6,7 @@ import Gtk from 'gi://Gtk?version=3.0';
import Gdk from 'gi://Gdk';
const EXT_PATH_DEFAULTS = [
+ '/run/current-system/sw/share/gnome-shell/extensions/',
GLib.get_home_dir() + '/.local/share/gnome-shell/extensions/',
'/usr/share/gnome-shell/extensions/',
];

View File

@@ -0,0 +1,51 @@
{
lib,
stdenv,
replaceVars,
fetchFromGitHub,
libpulseaudio,
python3,
}:
stdenv.mkDerivation {
pname = "gnome-shell-extension-sound-output-device-chooser";
# For gnome 42 support many commits not tagged yet are needed.
version = "unstable-2022-03-29";
src = fetchFromGitHub {
owner = "kgshank";
repo = "gse-sound-output-device-chooser";
rev = "76f7f59d23f5ffcd66555c7662f43c9cc1ce4742";
sha256 = "sha256-iPc95LmDsYizLg45wpU+vFx/N6MR2hewSHqoRsePC/4=";
};
patches = [
# Fix paths to libpulse and python
(replaceVars ./fix-paths.patch {
libpulse = "${libpulseaudio}/lib/libpulse.so";
python = python3.interpreter;
})
];
dontBuild = true;
passthru = {
extensionUuid = "sound-output-device-chooser@kgshank.net";
extensionPortalSlug = "sound-output-device-chooser";
};
makeFlags = [
"INSTALL_DIR=${placeholder "out"}/share/gnome-shell/extensions"
];
preInstall = ''
mkdir -p ${placeholder "out"}/share/gnome-shell/extensions
'';
meta = with lib; {
description = "GNOME Shell extension adding audio device chooser to panel";
license = licenses.gpl3Plus;
maintainers = [ ];
homepage = "https://github.com/kgshank/gse-sound-output-device-chooser";
};
}

View File

@@ -0,0 +1,26 @@
diff --git a/sound-output-device-chooser@kgshank.net/convenience.js b/sound-output-device-chooser@kgshank.net/convenience.js
index 54ad06f..0860531 100644
--- a/sound-output-device-chooser@kgshank.net/convenience.js
+++ b/sound-output-device-chooser@kgshank.net/convenience.js
@@ -142,7 +142,7 @@ function refreshCards() {
if (newProfLogic) {
_log("New logic");
let pyLocation = Me.dir.get_child("utils/pa_helper.py").get_path();
- let pythonExec = ["python", "python3", "python2"].find(cmd => isCmdFound(cmd));
+ let pythonExec = '@python@';
if (!pythonExec) {
_log("ERROR: Python not found. fallback to default mode");
_settings.set_boolean(Prefs.NEW_PROFILE_ID, false);
diff --git a/sound-output-device-chooser@kgshank.net/utils/libpulse_introspect.py b/sound-output-device-chooser@kgshank.net/utils/libpulse_introspect.py
index c4d2484..262608d 100644
--- a/sound-output-device-chooser@kgshank.net/utils/libpulse_introspect.py
+++ b/sound-output-device-chooser@kgshank.net/utils/libpulse_introspect.py
@@ -82,7 +82,7 @@ else:
_libraries = {}
-libpulse_library_name = find_library('pulse')
+libpulse_library_name = '@libpulse@'
if libpulse_library_name is None:
raise Exception('No libpulse.so library found!')

View File

@@ -0,0 +1,67 @@
{
lib,
stdenvNoCC,
fetchFromGitHub,
glib,
# These loosen security a bit, so we don't install them by default. See also:
# https://github.com/hardpixel/systemd-manager?tab=readme-ov-file#without-password-prompt
allowPolkitPolicy ? "none",
config,
systemd ? config.systemd.package,
}:
assert lib.elem allowPolkitPolicy [
"none"
"pkexec"
"systemctl"
];
stdenvNoCC.mkDerivation rec {
pname = "gnome-shell-extension-systemd-manager";
version = "19";
# Upstream doesn't post new versions in extensions.gnome.org anymore, see also:
# https://github.com/hardpixel/systemd-manager/issues/19
src = fetchFromGitHub {
owner = "hardpixel";
repo = "systemd-manager";
rev = "v${version}";
hash = "sha256-qmRDTyI2Kyr+ViNNgmna/E8xH1qzPyxzdPXyrwrgQGY=";
};
nativeBuildInputs = [ glib ];
postInstall = ''
rm systemd-manager@hardpixel.eu/schemas/gschemas.compiled
glib-compile-schemas systemd-manager@hardpixel.eu/schemas
mkdir -p $out/share/gnome-shell/extensions
mv systemd-manager@hardpixel.eu $out/share/gnome-shell/extensions
''
+ lib.optionalString (allowPolkitPolicy == "pkexec") ''
local bn=org.freedesktop.policykit.pkexec.systemctl.policy
mkdir -p $out/share/polkit-1/actions
substitute systemd-policies/$bn $out/share/polkit-1/actions/$bn \
--replace-fail /usr/bin/systemctl ${lib.getBin systemd}/bin/systemctl
''
+ lib.optionalString (allowPolkitPolicy == "systemctl") ''
install -Dm0644 \
systemd-policies/10-service_status.rules \
$out/share/polkit-1/rules.d/10-gnome-extension-systemd-manager.rules
'';
passthru = {
extensionUuid = "systemd-manager@hardpixel.eu";
extensionPortalSlug = "systemd-manager";
};
meta = with lib; {
description = "GNOME Shell extension to manage systemd services";
homepage = "https://github.com/hardpixel/systemd-manager";
license = licenses.gpl3Only;
maintainers = with maintainers; [
linsui
doronbehar
];
};
}

View File

@@ -0,0 +1,51 @@
{
lib,
stdenv,
replaceVars,
fetchFromGitHub,
taskwarrior2,
gettext,
runtimeShell,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-taskwhisperer";
version = "20";
src = fetchFromGitHub {
owner = "cinatic";
repo = "taskwhisperer";
rev = "v${version}";
sha256 = "sha256-UVBLFXsbOPRXC4P5laZ82Rs08yXnNnzJ+pp5fbx6Zqc=";
};
nativeBuildInputs = [
gettext
];
buildInputs = [
taskwarrior2
];
passthru = {
extensionUuid = "taskwhisperer-extension@infinicode.de";
extensionPortalSlug = "taskwhisperer";
};
makeFlags = [
"INSTALLBASE=${placeholder "out"}/share/gnome-shell/extensions"
];
patches = [
(replaceVars ./fix-paths.patch {
task = "${taskwarrior2}/bin/task";
})
];
meta = with lib; {
description = "GNOME Shell TaskWarrior GUI";
license = licenses.gpl3Plus;
maintainers = [ ];
homepage = "https://github.com/cinatic/taskwhisperer";
};
}

View File

@@ -0,0 +1,99 @@
diff --git a/taskwhisperer-extension@infinicode.de/metadata.json b/taskwhisperer-extension@infinicode.de/metadata.json
index 2f1471c..a84bdf4 100644
--- a/taskwhisperer-extension@infinicode.de/metadata.json
+++ b/taskwhisperer-extension@infinicode.de/metadata.json
@@ -6,7 +6,8 @@
"3.32",
"3.36",
"3.38",
- "40"
+ "40",
+ "41"
],
"url": "https://github.com/cinatic/taskwhisperer",
"uuid": "taskwhisperer-extension@infinicode.de",
diff --git a/taskwhisperer-extension@infinicode.de/services/taskService.js b/taskwhisperer-extension@infinicode.de/services/taskService.js
index df09cdf..df68c60 100644
--- a/taskwhisperer-extension@infinicode.de/services/taskService.js
+++ b/taskwhisperer-extension@infinicode.de/services/taskService.js
@@ -63,7 +63,7 @@ var loadTaskData = async ({ taskStatus, project, taskOrder }) => {
await syncTasks()
- const command = ['task', 'rc.json.array=on', statusFilter, projectFilter, 'export'].join(' ')
+ const command = ['@task@', 'rc.json.array=on', statusFilter, projectFilter, 'export'].join(' ')
let { output, error } = await run({ command })
@@ -110,7 +110,7 @@ var loadProjectsData = async taskStatus => {
await syncTasks()
- const command = ['task', 'rc.json.array=on', statusFilter, 'export'].join(' ')
+ const command = ['@task@', 'rc.json.array=on', statusFilter, 'export'].join(' ')
const { output: allTheTasks } = await run({ command })
let sortedUniqueProjects = []
@@ -129,7 +129,7 @@ var setTaskDone = async taskID => {
return
}
- const command = ['task', taskID.toString(), 'done'].join(' ')
+ const command = ['@task@', taskID.toString(), 'done'].join(' ')
const result = await run({ command, asJson: false })
if (!result.error) {
@@ -146,7 +146,7 @@ var setTaskUndone = async taskUUID => {
return
}
- const command = ['task', `uuid:${taskUUID}`, 'modify', 'status:pending'].join(' ')
+ const command = ['@task@', `uuid:${taskUUID}`, 'modify', 'status:pending'].join(' ')
const result = await run({ command, asJson: false })
if (!result.error) {
@@ -163,7 +163,7 @@ var startTask = async taskID => {
return
}
- const command = ['task', taskID.toString(), 'start'].join(' ')
+ const command = ['@task@', taskID.toString(), 'start'].join(' ')
const result = await run({ command, asJson: false })
if (!result.error) {
@@ -180,7 +180,7 @@ var stopTask = async taskID => {
return
}
- const command = ['task', taskID.toString(), 'stop'].join(' ')
+ const command = ['@task@', taskID.toString(), 'stop'].join(' ')
const result = await run({ command, asJson: false })
if (!result.error) {
@@ -195,7 +195,7 @@ var stopTask = async taskID => {
var createTask = async task => {
const params = _convertTaskToParams(task)
- const command = ['task', 'add', ...params].join(' ')
+ const command = ['@task@', 'add', ...params].join(' ')
const result = await run({ command, asJson: false })
if (!result.error) {
@@ -212,7 +212,7 @@ var modifyTask = async (taskUUID, task) => {
const params = _convertTaskToParams(task)
- const command = ['task', `uuid:${taskUUID}`, 'modify', ...params].join(' ')
+ const command = ['@task@', `uuid:${taskUUID}`, 'modify', ...params].join(' ')
const result = await run({ command, asJson: false })
if (!result.error) {
@@ -227,7 +227,7 @@ var syncTasks = async () => {
return
}
- const command = ['task', 'sync'].join(' ')
+ const command = ['@task@', 'sync'].join(' ')
const result = await run({ command, asJson: false })
_showProcessErrorNotificationIfError(result, 'Sync Tasks')

View File

@@ -0,0 +1,47 @@
{
stdenv,
lib,
fetchFromGitHub,
glib,
gnome-shell,
}:
stdenv.mkDerivation {
pname = "gnome-shell-extension-tilingnome";
version = "unstable-2019-09-19";
src = fetchFromGitHub {
owner = "rliang";
repo = "gnome-shell-extension-tilingnome";
rev = "f401c20c9721d85e6b3e30d1e822a200db370407";
sha256 = "1hq9g9bxqpzqrdj9zm0irld8r6q4w1m4b00jya7wsny8rzb1s0y2";
};
nativeBuildInputs = [ glib ];
buildPhase = ''
runHook preBuild
glib-compile-schemas .
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p "$out/share/gnome-shell/extensions/tilingnome@rliang.github.com"
cp -r * "$out/share/gnome-shell/extensions/tilingnome@rliang.github.com/"
runHook postInstall
'';
passthru = {
extensionUuid = "tilingnome@rliang.github.com";
extensionPortalSlug = "tilingnome";
};
meta = with lib; {
description = "Tiling window management for GNOME Shell";
license = licenses.gpl2;
maintainers = with maintainers; [ benley ];
homepage = "https://github.com/rliang/gnome-shell-extension-tilingnome";
platforms = gnome-shell.meta.platforms;
};
}

View File

@@ -0,0 +1,34 @@
{
lib,
stdenv,
fetchFromGitHub,
glib,
gettext,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-topicons-plus";
version = "27";
src = fetchFromGitHub {
owner = "phocean";
repo = "TopIcons-plus";
rev = version;
sha256 = "1p3jlvs4zgnrvy8am7myivv4rnnshjp49kg87rd22qqyvcz51ykr";
};
buildInputs = [ glib ];
nativeBuildInputs = [ gettext ];
makeFlags = [ "INSTALL_PATH=$(out)/share/gnome-shell/extensions" ];
passthru.extensionUuid = "TopIcons@phocean.net";
meta = with lib; {
description = "Brings all icons back to the top panel, so that it's easier to keep track of apps running in the backround";
license = licenses.gpl2Only;
maintainers = with maintainers; [ eperuffo ];
homepage = "https://github.com/phocean/TopIcons-plus";
};
}

View File

@@ -0,0 +1,50 @@
{
lib,
stdenv,
gnome-shell,
fetchFromGitHub,
xprop,
glib,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-unite";
version = "83";
src = fetchFromGitHub {
owner = "hardpixel";
repo = "unite-shell";
rev = "v${version}";
hash = "sha256-L920BTDEQd/XP+Qa/f4VniCTJhVGgjipCcTAYPdfXg8=";
};
passthru = {
extensionUuid = "unite@hardpixel.eu";
extensionPortalSlug = "unite";
};
nativeBuildInputs = [ glib ];
buildInputs = [ xprop ];
buildPhase = ''
runHook preBuild
glib-compile-schemas --strict --targetdir="unite@hardpixel.eu/schemas/" "unite@hardpixel.eu/schemas"
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share/gnome-shell/extensions
cp -r "unite@hardpixel.eu" $out/share/gnome-shell/extensions
runHook postInstall
'';
meta = with lib; {
description = "Unite is a GNOME Shell extension which makes a few layout tweaks to the top panel and removes window decorations to make it look like Ubuntu Unity Shell";
license = licenses.gpl3Only;
maintainers = with maintainers; [ rhoriguchi ];
homepage = "https://github.com/hardpixel/unite-shell";
broken = versionOlder gnome-shell.version "3.32";
};
}

View File

@@ -0,0 +1,443 @@
#!/usr/bin/env nix-shell
#!nix-shell -I nixpkgs=../../../.. -i python3 -p python3
### After making change:
### - Format the script by running: nix run nixpkgs#black pkgs/desktops/gnome/extensions/update-extensions.py
### - Run the unit test by running: python3 -m unittest pkgs/desktops/gnome/extensions/update-extensions.py
### - Run the type checking by running: nix run nixpkgs#mypy pkgs/desktops/gnome/extensions/update-extensions.py
import base64
import json
import logging
import argparse
import unittest
import subprocess
import urllib.error
import urllib.request
from contextlib import contextmanager
from operator import itemgetter
from pathlib import Path
from typing import Any
# We don't want all those deprecated legacy extensions
# Group extensions by GNOME "major" version for compatibility reasons
supported_versions = {
"38": "3.38",
"40": "40",
"41": "41",
"42": "42",
"43": "43",
"44": "44",
"45": "45",
"46": "46",
"47": "47",
"48": "48",
}
# shell versions that we want to put into the gnomeExtensions attr set
versions_to_merge = ["46", "47", "48"]
# Some type alias to increase readability of complex compound types
PackageName = str
ShellVersion = str
Uuid = str
ExtensionVersion = int
updater_dir_path = Path(__file__).resolve().parent
def fetch_extension_data(uuid: str, version: str) -> tuple[str, str]:
"""
Download the extension and hash it. We use `nix-prefetch-url` for this for efficiency reasons.
Returns a tuple with the hash (Nix-compatible) of the zip file's content and the base64-encoded content of its metadata.json.
"""
# The download URLs follow this schema
uuid = uuid.replace("@", "")
url: str = (
f"https://extensions.gnome.org/extension-data/{uuid}.v{version}.shell-extension.zip"
)
# Download extension and add the zip content to nix-store
for _ in range(0, 10):
process = subprocess.run(
["nix-prefetch-url", "--unpack", "--print-path", url],
capture_output=True,
text=True,
)
if process.returncode == 0:
break
else:
logging.warning(f"Nix-prefetch-url failed for {url}:")
logging.warning(f"Stderr: {process.stderr}")
logging.warning("Retrying")
if process.returncode != 0:
raise Exception(
"Retried 10 times, but still failed to download the extension. Exiting."
)
lines = process.stdout.splitlines()
# Get hash from first line of nix-prefetch-url output
hash = lines[0].strip()
# Get path from second line of nix-prefetch-url output
path = Path(lines[1].strip())
# Get metadata.json content from nix-store
with open(path / "metadata.json", "r") as out:
metadata = base64.b64encode(out.read().encode("ascii")).decode()
return hash, metadata
def generate_extension_versions(
extension_version_map: dict[ShellVersion, ExtensionVersion],
uuid: str,
) -> dict[ShellVersion, dict[str, str]]:
"""
Takes in a mapping from shell versions to extension versions and transforms it the way we need it:
- Only take one extension version per GNOME Shell major version (as per `supported_versions`)
- Filter out versions that only support old GNOME versions
- Download the extension and hash it
"""
# Determine extension version per shell version
extension_versions: dict[ShellVersion, ExtensionVersion] = {}
for shell_version, version_prefix in supported_versions.items():
# Newest compatible extension version
extension_version: int | None = max(
(
int(ext_ver)
for shell_ver, ext_ver in extension_version_map.items()
if (shell_ver.startswith(version_prefix))
),
default=None,
)
# Extension is not compatible with this GNOME version
if not extension_version:
continue
extension_versions[shell_version] = extension_version
# Download information once for all extension versions chosen above
extension_info_cache: dict[ExtensionVersion, tuple[str, str]] = {}
for extension_version in sorted(set(extension_versions.values())):
logging.debug(f"[{uuid}] Downloading v{extension_version}")
extension_info_cache[extension_version] = fetch_extension_data(
uuid,
str(extension_version),
)
# Fill map
extension_versions_full: dict[ShellVersion, dict[str, str]] = {}
for shell_version, extension_version in extension_versions.items():
sha256, metadata = extension_info_cache[extension_version]
extension_versions_full[shell_version] = {
"version": str(extension_version),
"sha256": sha256,
# The downloads are impure, their metadata.json may change at any time.
# Thus, we back it up / pin it to remain deterministic
# Upstream issue: https://gitlab.gnome.org/Infrastructure/extensions-web/-/issues/137
"metadata": metadata,
}
return extension_versions_full
def pname_from_url(url: str) -> tuple[str, str]:
"""
Parse something like "/extension/1475/battery-time/" and output ("battery-time", "1475")
"""
url = url.split("/") # type: ignore
return url[3], url[2]
def process_extension(extension: dict[str, Any]) -> dict[str, Any] | None:
"""
Process an extension. It takes in raw scraped data and downloads all the necessary information that buildGnomeExtension.nix requires
Input: a json object of one extension queried from the site. It has the following schema (only important key listed):
{
"uuid": str,
"name": str,
"description": str,
"link": str,
"shell_version_map": {
str: { "version": int, … },
},
}
"uuid" is an extension UUID that looks like this (most of the time): "extension-name@username.domain.tld".
Don't make any assumptions on it, and treat it like an opaque string!
"link" follows the following schema: "/extension/$number/$string/"
The number is monotonically increasing and unique to every extension.
The string is usually derived from the extension name (but shortened, kebab-cased and URL friendly).
It may diverge from the actual name.
The keys of "shell_version_map" are GNOME Shell version numbers.
Output: a json object to be stored, or None if the extension should be skipped. Schema:
{
"uuid": str,
"name": str,
"pname": str,
"description": str,
"link": str,
"shell_version_map": {
str: { "version": int, "sha256": str, "metadata": <hex> },
}
}
Only "uuid" gets passed along unmodified. "name", "description" and "link" are taken from the input, but sanitized.
"pname" gets generated from other fields and "shell_version_map" has a completely different structure than the input
field with the same name.
"""
uuid = extension["uuid"]
# Yeah, there are some extensions without any releases
if not extension["shell_version_map"]:
return None
logging.info(f"Processing '{uuid}'")
# Input is a mapping str -> { version: int, … }
# We want to map shell versions to extension versions
shell_version_map: dict[ShellVersion, int] = {
k: v["version"] for k, v in extension["shell_version_map"].items()
}
# Transform shell_version_map to be more useful for us. Also throw away unwanted versions
shell_version_map: dict[ShellVersion, dict[str, str]] = generate_extension_versions(shell_version_map, uuid) # type: ignore
# No compatible versions found
if not shell_version_map:
return None
# Fetch a human-readable name for the package.
(pname, _pname_id) = pname_from_url(extension["link"])
return {
"uuid": uuid,
"name": extension["name"],
"pname": pname,
"description": extension["description"],
"link": "https://extensions.gnome.org" + extension["link"],
"shell_version_map": shell_version_map,
}
@contextmanager
def request(url: str, retries: int = 5, retry_codes: list[int] = [500, 502, 503, 504]):
req = urllib.request.Request(
url,
headers={
"User-Agent": "NixpkgsGnomeExtensionUpdate (+https://github.com/NixOS/nixpkgs)"
},
)
for attempt in range(retries + 1):
try:
with urllib.request.urlopen(req) as response:
yield response
break
except urllib.error.HTTPError as e:
if e.code in retry_codes and attempt < retries:
logging.warning(f"Error while fetching {url}. Retrying: {e}")
else:
raise e
def scrape_extensions_index() -> list[dict[str, Any]]:
"""
Scrape the list of extensions by sending search queries to the API. We simply go over it
page by page until we hit a non-full page or a 404 error.
The returned list is sorted by the age of the extension, in order to be deterministic.
"""
page = 0
extensions = []
while True:
page += 1
logging.info("Scraping page " + str(page))
try:
with request(
f"https://extensions.gnome.org/extension-query/?n_per_page=25&page={page}"
) as response:
data = json.loads(response.read().decode())["extensions"]
response_length = len(data)
for extension in data:
extensions.append(extension)
# If our page isn't "full", it must have been the last one
if response_length < 25:
logging.debug(
f"\tThis page only has {response_length} entries, so it must be the last one."
)
break
except urllib.error.HTTPError as e:
if e.code == 404:
# We reached past the last page and are done now
break
else:
raise
# `pk` is the primary key in the extensions.gnome.org database. Sorting on it will give us a stable,
# deterministic ordering.
extensions.sort(key=itemgetter("pk"))
return extensions
def fetch_extensions() -> list[dict[str, Any]]:
raw_extensions = scrape_extensions_index()
logging.info(f"Downloaded {len(raw_extensions)} extensions. Processing …")
processed_extensions: list[dict[str, Any]] = []
for num, raw_extension in enumerate(raw_extensions):
processed_extension = process_extension(raw_extension)
if processed_extension:
processed_extensions.append(processed_extension)
logging.debug(f"Processed {num + 1} / {len(raw_extensions)}")
return processed_extensions
def serialize_extensions(processed_extensions: list[dict[str, Any]]) -> None:
# We micro-manage a lot of the serialization process to keep the diffs optimal.
# We generally want most of the attributes of an extension on one line,
# but then each of its supported versions with metadata on a new line.
with open(updater_dir_path / "extensions.json", "w") as out:
for index, extension in enumerate(processed_extensions):
# Manually pretty-print the outermost array level
if index == 0:
out.write("[ ")
else:
out.write(", ")
# Dump each extension into a single-line string forst
serialized_extension = json.dumps(extension, ensure_ascii=False)
# Inject line breaks for each supported version
for version in supported_versions:
# This one only matches the first entry
serialized_extension = serialized_extension.replace(
f'{{"{version}": {{',
f'{{\n "{version}": {{',
)
# All other entries
serialized_extension = serialized_extension.replace(
f', "{version}": {{',
f',\n "{version}": {{',
)
# One last line break around the closing braces
serialized_extension = serialized_extension.replace("}}}", "}\n }}")
out.write(serialized_extension)
out.write("\n")
out.write("]\n")
def find_collisions(
extensions: list[dict[str, Any]],
versions: list[str],
) -> dict[PackageName, list[Uuid]]:
package_name_registry: dict[PackageName, set[Uuid]] = {}
for extension in extensions:
pname = extension["pname"]
uuid = extension["uuid"]
for shell_version in versions:
if shell_version in extension["shell_version_map"]:
package_name_registry.setdefault(pname, set()).add(uuid)
return {
pname: sorted(uuids)
for pname, uuids in sorted(package_name_registry.items())
if len(uuids) > 1
}
def main() -> None:
logging.basicConfig(level=logging.DEBUG)
parser = argparse.ArgumentParser()
parser.add_argument(
"--skip-fetch",
action="store_true",
help="Skip fetching extensions. When this option is set, the script does not fetch extensions from the internet, but checks for name collisions.",
)
args = parser.parse_args()
if not args.skip_fetch:
processed_extensions = fetch_extensions()
serialize_extensions(processed_extensions)
logging.info(
f"Done. Writing results to extensions.json ({len(processed_extensions)} extensions in total)"
)
with open(updater_dir_path / "extensions.json", "r") as out:
extensions = json.load(out)
collisions = find_collisions(extensions, versions_to_merge)
with open(updater_dir_path / "collisions.json", "w") as out:
json.dump(collisions, out, indent=2, ensure_ascii=False)
out.write("\n")
logging.info(
"Done. Writing name collisions to collisions.json (please check manually)"
)
if __name__ == "__main__":
main()
class FindCollisions(unittest.TestCase):
extensions = [
{
"pname": "foo",
"uuid": "foo_38_to_40@doe.example",
"shell_version_map": {
"38": {},
"40": {},
},
},
{
"pname": "bar",
"uuid": "bar_42_to_45@chulsoo.example",
"shell_version_map": {
"42": {},
"43": {},
"44": {},
"45": {},
},
},
{
"pname": "bar",
"uuid": "bar_44_to_47@younghee.example",
"shell_version_map": {
"44": {},
"45": {},
"46": {},
"47": {},
},
},
]
def test_no_collision(self) -> None:
self.assertEqual(
{},
find_collisions(self.extensions, ["40", "41", "42"]),
)
def test_collision(self) -> None:
self.assertEqual(
{
"bar": [
"bar_42_to_45@chulsoo.example",
"bar_44_to_47@younghee.example",
],
},
find_collisions(self.extensions, ["45", "46", "47"]),
)

View File

@@ -0,0 +1,42 @@
{
stdenv,
lib,
fetchFromGitHub,
meson,
ninja,
gitUpdater,
}:
stdenv.mkDerivation rec {
pname = "gnome-shell-extension-valent";
version = "1.0.0.alpha.48";
src = fetchFromGitHub {
owner = "andyholmes";
repo = "gnome-shell-extension-valent";
tag = "v${version}";
hash = "sha256-j5590Emcga3Wp7/lC/ni2NpEC3bkR2/vT4Cq/m8GvBM=";
};
nativeBuildInputs = [
meson
ninja
];
passthru = {
extensionUuid = "valent@andyholmes.ca";
extensionPortalSlug = "valent";
updateScript = gitUpdater {
rev-prefix = "v";
};
};
meta = {
description = "GNOME Shell integration for Valent";
homepage = "https://valent.andyholmes.ca/";
changelog = "https://github.com/andyholmes/gnome-shell-extension-valent/blob/${src.rev}/CHANGELOG.md";
license = lib.licenses.gpl3Plus;
maintainers = [ ];
platforms = lib.platforms.linux;
};
}

View File

@@ -0,0 +1,40 @@
{
lib,
stdenv,
fetchFromGitHub,
gnome-shell,
}:
stdenv.mkDerivation {
pname = "gnome-shell-extension-window-corner-preview";
version = "unstable-2019-04-03";
src = fetchFromGitHub {
owner = "medenagan";
repo = "window-corner-preview";
rev = "a95bb1389d94474efab7509aac592fb58fff6006";
sha256 = "03v18j9l0fb64xrg3swf1vcgl0kpgwjlp8ddn068bpvghrsvgfah";
};
dontBuild = true;
passthru = {
extensionUuid = "window-corner-preview@fabiomereu.it";
extensionPortalSlug = "window-corner-preview";
};
installPhase = ''
runHook preInstall
mkdir -p $out/share/gnome-shell/extensions
cp -r "window-corner-preview@fabiomereu.it" $out/share/gnome-shell/extensions
runHook postInstall
'';
meta = with lib; {
description = "GNOME Shell extension showing a video preview on the corner of the screen";
license = licenses.mit;
maintainers = [ ];
homepage = "https://github.com/medenagan/window-corner-preview";
broken = lib.versionAtLeast gnome-shell.version "3.32"; # Doesn't support 3.34
};
}