main
  1{
  2  den,
  3  lib,
  4  ...
  5}: {
  6  den.aspects.desktop.browser.floorp = {
  7    persistHome = {config, ...}: {
  8      directories = [
  9        "${config.home.homeDirectory}/.floorp"
 10      ];
 11    };
 12
 13    homeManager = {
 14      host,
 15      pkgs,
 16      ...
 17    }: let
 18      fontsCfg = host.settings.desktop.style.fonts;
 19    in {
 20      programs.floorp = {
 21        enable = true;
 22        languagePacks = ["zh-CN" "en-US"];
 23
 24        policies = {
 25          DisableAppUpdate = true;
 26          DisablePocket = true;
 27          DisableSetDesktopBackground = true;
 28          DisableTelemetry = true;
 29          DontCheckDefaultBrowser = true;
 30          ExtensionUpdate = false;
 31          NoDefaultBookmarks = true;
 32          OfferToSaveLogins = false;
 33          PasswordManagerEnabled = false;
 34        };
 35
 36        profiles.default = {
 37          id = 0;
 38          isDefault = true;
 39
 40          search = {
 41            force = true;
 42            default = "kagi";
 43            privateDefault = "kagi";
 44            order = [
 45              "kagi"
 46              "bing"
 47              "google"
 48              "ddg"
 49            ];
 50            engines = {
 51              kagi = {
 52                name = "Kagi";
 53                description = "A privacy-focused, user-centric search engine.";
 54                urls = [
 55                  {template = "https://kagi.com/search?q={searchTerms}";}
 56                  {
 57                    type = "application/x-suggestions+json";
 58                    template = "https://kagisuggest.com/api/autosuggest?q={searchTerms}";
 59                  }
 60                ];
 61                iconMapObj = {
 62                  "16" = "https://kagi.com/favicon-16x16.png";
 63                  "32" = "https://kagi.com/favicon-32x32.png";
 64                };
 65                definedAliases = ["@kagi"];
 66              };
 67
 68              baidu.metaData.hidden = true;
 69              startpage.metaData.hidden = true;
 70              "you.com".metaData.hidden = true;
 71            };
 72          };
 73
 74          extensions.force = true;
 75          extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
 76            ublock-origin
 77            bitwarden
 78            tampermonkey
 79            kiss-translator
 80            libredirect
 81          ];
 82
 83          settings = {
 84            # == General ==
 85            "browser.startup.page" = 3; # Open prev session pages
 86            "browser.tabs.unloadOnLowMemory" = true;
 87            "widget.use-xdg-desktop-portal.file-picker" = 1;
 88            # No first run
 89            "app.normandy.first_run" = false;
 90            "doh-rollout.doneFirstRun" = true;
 91            "toolkit.telemetry.reportingpolicy.firstRun" = false;
 92            "trailhead.firstrun.didSeeAboutWelcome" = true;
 93            "browser.toolbarbuttons.introduced.sidebar-button" = true;
 94            "sidebar.old-sidebar.has-used" = true;
 95            "sidebar.new-sidebar.has-used" = true;
 96            "floorp.browser.welcome.page.shown" = true;
 97            # Language
 98            "general.useragent.locale" = "zh-CN";
 99            "intl.locale.requested" = "zh-CN,en-US";
100            "browser.translations.mostRecentTargetLanguages" = "zh-Hans";
101            # No ads
102            "browser.urlbar.suggest.topsites" = false;
103            "browser.urlbar.suggest.trending" = false;
104            "browser.newtabpage.pinned" = [];
105            "browser.newtabpage.activity-stream.showSponsored" = false;
106            "browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
107            # == Telemetry ==
108            "toolkit.telemetry.unified" = false;
109            "toolkit.telemetry.enabled" = false;
110            "toolkit.telemetry.server" = "data:,";
111            "toolkit.telemetry.archive.enabled" = false;
112            "toolkit.telemetry.newProfilePing.enabled" = false;
113            "toolkit.telemetry.shutdownPingSender.enabled" = false;
114            "toolkit.telemetry.updatePing.enabled" = false;
115            "toolkit.telemetry.bhrPing.enabled" = false;
116            "toolkit.telemetry.firstShutdownPing.enabled" = false;
117            "toolkit.telemetry.shutdownPingSender.enabledFirstsession" = false;
118            "browser.ping-centre.telemetry" = false;
119            "browser.newtabpage.activity-stream.feeds.telemetry" = false;
120            "browser.newtabpage.activity-stream.telemetry" = false;
121            # == Apperance ==
122            # Fonts
123            "font.name.monospace.x-western" = (builtins.elemAt fontsCfg.monospace 0).name;
124            "font.name.sans-serif.x-western" = (builtins.elemAt fontsCfg.sansSerif 0).name;
125            "font.name.serif.x-western" = (builtins.elemAt fontsCfg.serif 0).name;
126            "font.size.monospace.x-western" = builtins.floor (
127              (fontsCfg.sizes.terminal * 4.0 / 3.0) + 0.5
128            );
129            "font.size.variable.x-western" = builtins.floor (
130              (fontsCfg.sizes.applications * 4.0 / 3.0) + 0.5
131            );
132            "browser.newtabpage.activity-stream.feeds.topsites" = false;
133            "browser.newtabpage.activity-stream.default.sites" = "";
134            "browser.toolbars.bookmarks.visibility" = "always";
135            "sidebar.verticalTabs" = true;
136            "sidebar.main.tools" = "syncedtabs";
137            "sidebar.visibility" = "expand-on-hover";
138            # Floorp's new tab page
139            "floorp.newtab.configs" = {
140              "backround"."type" = "none";
141              "components" = {
142                "topSites" = false;
143                "clock" = false;
144                "searchBar" = true;
145                "firefoxLayout" = true;
146              };
147              "searchBar" = {"searchEngine" = "default";};
148              "topSites" = {
149                "pinned" = [];
150                "blocked" = [];
151              };
152            };
153            # panelSideBar
154            "floorp.panelSidebar.enabled" = true;
155            "floorp.panelSidebar.config" = {
156              "autoUnload" = false;
157              "position_start" = true;
158              "globalWidth" = 400;
159              "displayed" = true;
160              "webExtensionRunningEnabled" = false;
161            };
162            "floorp.panelSidebar.data"."data" =
163              (lib.map (x: {
164                "id" = "default-panel-${x}";
165                "url" = "floorp//${x}";
166                "width" = 0;
167                "type" = "static";
168              }) ["bookmarks" "history" "downloads"])
169              ++ (lib.map (url: let
170                  id = lib.pipe url [
171                    (x: lib.removePrefix "http://" x)
172                    (x: lib.removePrefix "https://" x)
173                    (x: lib.splitString "?" x)
174                    (x: lib.elemAt x 0)
175                    (x: lib.replaceStrings ["/" "."] ["-" "-"] x)
176                    (x: lib.removeSuffix "-" x)
177                    (x: "panel-${x}")
178                  ];
179                in {
180                  inherit id url;
181                  "width" = 0;
182                  "userContextId" = 0;
183                  "zoomLevel" = null;
184                  "type" = "web";
185                }) [
186                  "https://translate.kagi.com"
187                  "https://squoosh.app"
188                ]);
189            # Workspace
190            "floorp.workspaces.enabled" = true;
191            "floorp.workspaces.v4.config" = {
192              "manageOnBms" = true;
193              "showWorkspaceNameOnToolbar" = true;
194            };
195            # Top toolbar
196            "browser.uiCustomization.state" = {
197              "placements" = {
198                "widget-overflow-fixed-list" = [];
199                "unified-extensions-area" = [
200                  "firefox_tampermonkey_net-browser-action" # Tampermonkey
201                  "ublock0_raymondhill_net-browser-action" # uBlock Origin
202                ];
203                "nav-bar" = [
204                  "sidebar-button"
205                  "back-button"
206                  "forward-button"
207                  "stop-reload-button"
208                  "vertical-spacer"
209                  "urlbar-container"
210                  "_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action" # Bitwarden
211                  "unified-extensions-button"
212                  "fxa-toolbar-menu-button"
213                ];
214                "toolbar-menubar" = ["menubar-items"];
215                "TabsToolbar" = [];
216                "vertical-tabs" = ["tabbrowser-tabs"];
217                "PersonalToolbar" = ["personal-bookmarks"];
218                "nora-statusbar" = [
219                  "screenshot-button"
220                  "fullscreen-button"
221                  "status-text"
222                ];
223              };
224              "seen" = ["developer-button"];
225              "dirtyAreaCache" = [];
226            };
227          };
228        };
229      };
230    };
231  };
232
233  den.aspects.desktop.browser.floorp.mkDefault = {
234    includes = [(den.aspects.desktop.browser.default ["floorp.desktop"])];
235  };
236
237  den.aspects.desktop.browser.floorp.themes = {
238    catppuccin = {
239      homeManager = {pkgs, ...}: let
240        # From catppuccin/nix
241        # Use static version to avoid IFD
242        themes = lib.importJSON ./catppuccin-firefox-themes.json;
243      in {
244        programs.floorp = {
245          profiles.default = {
246            extensions = {
247              packages = with pkgs.nur.repos.rycee.firefox-addons; [
248                firefox-color
249              ];
250              settings."FirefoxColor@mozilla.com" = {
251                force = true;
252                settings = {
253                  firstRunDone = true;
254                  theme = themes.mocha.mauve;
255                };
256              };
257            };
258          };
259        };
260      };
261    };
262  };
263}