summaryrefslogtreecommitdiff
path: root/modules/home/arkenfox/default.nix
blob: 2841df16dde83d71a2d8cba1931629ab718d2d36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
{
  config,
  lib,
  pkgs,
  ...
}:

let
  # ===
  ## Pollyfill from mkFirefoxModule
  ## https://github.com/nix-community/home-manager/blob/70fbbf05a5594b0a72124ab211bff1d502c89e3f/modules/programs/firefox/mkFirefoxModule.nix
  # ===

  inherit (pkgs.stdenv.hostPlatform) isDarwin;

  cfg = config.programs.firefox;

  profilesPath = if isDarwin then "${cfg.configPath}/Profiles" else cfg.configPath;

  # ===
  ## Actual module
  # ===

  arkenfoxVersions = lib.mapAttrs (
    tag: hash:
    pkgs.fetchFromGitHub {
      owner = "arkenfox";
      repo = "user.js";
      inherit tag hash;
    }
  ) (lib.importJSON ./arkenfox-hashes.json);

  latestVersionIn =
    versions: lib.elemAt (lib.sort lib.versionOlder versions) (lib.length versions - 1);

  arkenfoxSubmodule =
    { config, ... }:
    {
      options = {
        arkenfox = {
          enable = lib.mkEnableOption "arkenfox";

          version = lib.mkOption {
            type = lib.types.str;
            default = latestVersionIn (lib.attrNames arkenfoxVersions);
            description = ''
              Version of Arkenfox to apply.

              This should match a tag in https://github.com/arkenfox/user.js.
            '';
          };

          source = lib.mkOption {
            type = lib.types.path;
            internal = true;
          };
        };
      };

      config = {
        arkenfox.source = lib.mkDefault arkenfoxVersions.${config.arkenfox.version};
      };
    };
in

{
  options.programs.firefox.profiles = lib.mkOption {
    type = lib.types.attrsOf (lib.types.submodule arkenfoxSubmodule);
  };

  config = {
    home = {
      file = lib.mkMerge (
        lib.mapAttrsToList (lib.const (
          profile:

          let
            shouldCreateUserJs =
              profile.preConfig != ""
              || profile.settings != { }
              || profile.extraConfig != ""
              || profile.bookmarks != [ ]
              || profile.arkenfox.enable;

            userJsPath = "${profilesPath}/${profile.path}/user.js";
            prefsCleanerPath = dirOf userJsPath + "/prefsCleaner.sh";

            homeManagerUserJs =
              pkgs.writeText "home-manager-firefox-profile-${profile.name}-home-manager-userjs"
                (toString config.home.file.${userJsPath}.text);
          in

          {
            ${userJsPath} = lib.mkIf shouldCreateUserJs {
              source = pkgs.runCommand "home-manager-firefox-profile-${profile.name}-userjs" { } ''
                echo "// Generated by getchoo's Arkenfox module" > $out
                echo >> $out
                cat ${profile.arkenfox.source + "/user.js"} >> $out
                echo >> $out
                cat ${homeManagerUserJs} >> $out
              '';

              onChange = ''
                if [[ -f ${config.home.homeDirectory}/${dirOf prefsCleanerPath}/prefs.js ]]; then
                  ${config.home.homeDirectory}/${prefsCleanerPath} -d -s
                fi
              '';
            };

            ${prefsCleanerPath} = lib.mkIf profile.arkenfox.enable {
              # Make sure the script doesn't traverse symlinks, else it'll end up trying to write to the store
              source = pkgs.runCommand "home-manager-firefox-profile-${profile.name}-prefs-cleaner" { } ''
                cp ${profile.arkenfox.source + "/prefsCleaner.sh"} $out
                chmod +w $out
                substituteInPlace $out \
                  --replace-fail \
                  'SCRIPT_FILE=$(readlink -f "''${BASH_SOURCE[0]}" 2>/dev/null || greadlink -f "''${BASH_SOURCE[0]}" 2>/dev/null)' \
                  'SCRIPT_FILE="''${BASH_SOURCE[0]}"'
              '';

              executable = true;
            };
          }
        )) cfg.profiles
      );
    };
  };
}