Add vscode and collabora gtimelog sources to flake

- We'll be installing collabora's build of gtimelog and vscode with extensions
- Collabora gtimelog allows uploading gtimelog logs to chronophage automatically
- Some VSCode extensions are available on nixpkgs, but the majority are not.
  The marketplace flake automatically packages and updates them from the official
  extensions repos, allowing the top 10k extensions to be enabled much more
  easily
- Install collabora gtimelog from this later source
diff --git a/flake.lock b/flake.lock
index 8fb46fe..2b7cdb0 100644
--- a/flake.lock
+++ b/flake.lock
@@ -15,6 +15,37 @@
         "type": "github"
       }
     },
+    "flake-utils_2": {
+      "locked": {
+        "lastModified": 1659877975,
+        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "gtimelog": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1624374909,
+        "narHash": "sha256-Ls6FpmssAhheVEsi/BQgUb41V7eE7yMdkwt+mPWkRmI=",
+        "ref": "refs/heads/master",
+        "rev": "ae1f65c2088c6ab167b3cf142f80bd04720d1886",
+        "revCount": 459,
+        "type": "git",
+        "url": "https://gitlab.collabora.com/collabora/gtimelog.git"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://gitlab.collabora.com/collabora/gtimelog.git"
+      }
+    },
     "home-manager": {
       "inputs": {
         "nixpkgs": [
@@ -36,6 +67,27 @@
         "type": "github"
       }
     },
+    "home-manager-unstable": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "utils": "utils"
+      },
+      "locked": {
+        "lastModified": 1661573386,
+        "narHash": "sha256-pBEg8iY00Af/SAtU2dlmOAv+2x7kScaGlFRDjNoVJO8=",
+        "owner": "nix-community",
+        "repo": "home-manager",
+        "rev": "d89bdff445eadff03fe414e9c30486bc8166b72b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "home-manager",
+        "type": "github"
+      }
+    },
     "impermanence": {
       "locked": {
         "lastModified": 1646131459,
@@ -83,6 +135,22 @@
         "type": "github"
       }
     },
+    "nixpkgs_2": {
+      "locked": {
+        "lastModified": 1660464579,
+        "narHash": "sha256-kzA9rwh0wS6CwUnFHAQ7dhJCowMPfRbvixVeOKnUmjo=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "b02538b16f6c5e1dbfce1033b27946e25c019b3b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
     "registry": {
       "flake": false,
       "locked": {
@@ -102,11 +170,14 @@
     "root": {
       "inputs": {
         "flake-utils": "flake-utils",
+        "gtimelog": "gtimelog",
         "home-manager": "home-manager",
+        "home-manager-unstable": "home-manager-unstable",
         "impermanence": "impermanence",
         "nixpkgs": "nixpkgs",
         "registry": "registry",
-        "sops-nix": "sops-nix"
+        "sops-nix": "sops-nix",
+        "vscode-extensions": "vscode-extensions"
       }
     },
     "sops-nix": {
@@ -129,6 +200,40 @@
         "repo": "sops-nix",
         "type": "github"
       }
+    },
+    "utils": {
+      "locked": {
+        "lastModified": 1653893745,
+        "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "vscode-extensions": {
+      "inputs": {
+        "flake-utils": "flake-utils_2",
+        "nixpkgs": "nixpkgs_2"
+      },
+      "locked": {
+        "lastModified": 1662019250,
+        "narHash": "sha256-7fLV45jqj0v+q3dUM+iRWv9rJzqKcRimah8MaBe621Q=",
+        "owner": "AmeerTaweel",
+        "repo": "nix-vscode-marketplace",
+        "rev": "6d660610d15ad26be92f1c09725ed67f8d9bf105",
+        "type": "github"
+      },
+      "original": {
+        "owner": "AmeerTaweel",
+        "repo": "nix-vscode-marketplace",
+        "type": "github"
+      }
     }
   },
   "root": "root",
diff --git a/flake.nix b/flake.nix
index 701ba47..b68e2b1 100644
--- a/flake.nix
+++ b/flake.nix
@@ -3,15 +3,22 @@
   inputs = {
     nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
     flake-utils.url = "github:numtide/flake-utils";
+    vscode-extensions.url = "github:AmeerTaweel/nix-vscode-marketplace";
     registry = {
       url = "github:nixos/flake-registry";
       flake = false;
     };
     home-manager.url = "github:nix-community/home-manager/release-22.05";
+    home-manager-unstable.url = "github:nix-community/home-manager";
     sops-nix.url = "github:Mic92/sops-nix";
     impermanence.url = "github:nix-community/impermanence";
+    gtimelog = {
+      url = "git+https://gitlab.collabora.com/collabora/gtimelog.git";
+      flake = false;
+    };
 
     home-manager.inputs.nixpkgs.follows = "nixpkgs";
+    home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs";
     sops-nix.inputs.nixpkgs.follows = "nixpkgs";
     impermanence.inputs.nixpkgs.follows = "nixpkgs";
   };
@@ -28,6 +35,46 @@
       utils = import ./utils nixpkgs.lib;
 
       username = "minion";
+
+      isAttrType = type:
+        if builtins.elem type.name ["submodule" ]
+        then true
+        else if type ? nestedTypes.elemType
+        then isAttrType type.nestedTypes.elemType
+        else false;
+
+      normalizeOptions = options:
+        if
+          nixpkgs.lib.traceSeqN 2 {
+            inherit options;
+            type = builtins.typeOf options;
+          }
+          builtins.typeOf
+          options
+          == "set"
+        then
+          nixpkgs.lib.mapAttrs (
+            name: value:
+              if
+                nixpkgs.lib.traceSeqN 3 {
+                  inherit name value;
+                  hasGetSubOpts = value ? getSubOptions;
+                  hasType = value ? type;
+                  isAttrType = value ? type && isAttrType value.type;
+                  typeName = value.type.name or "unnamed";
+                  type = builtins.typeOf value;
+                } (builtins.typeOf value)
+                == "set"
+              then
+                nixpkgs.lib.traceVal (normalizeOptions (
+                  if value ? type && isAttrType value.type
+                  then nixpkgs.lib.traceVal (value.type.getSubOptions [])
+                  else nixpkgs.lib.traceVal value
+                ))
+              else value
+          )
+          options
+        else options;
     in {
       packages.nixosConfigurations = {
         default = nixpkgs.lib.nixosSystem {
@@ -40,6 +87,10 @@
                 args
                 // {
                   home = args.config.home-manager.users.${username};
+                  home-options =
+                    nixpkgs.lib.traceVal (normalizeOptions
+                      (args.options.home-manager.users.type.getSubOptions []));
+                  inherit system;
                 }))
             ])
             {
@@ -47,7 +98,7 @@
             }
           ];
 
-          specialArgs = inputs // {inherit username pkgs;};
+          specialArgs = inputs // {inherit username;};
         };
       };
       devShell = pkgs.mkShell {
diff --git a/modules/gtimelog.nix b/modules/gtimelog.nix
new file mode 100644
index 0000000..77f5f66
--- /dev/null
+++ b/modules/gtimelog.nix
@@ -0,0 +1,35 @@
+{
+  pkgs,
+  username,
+  gtimelog,
+  lib,
+  ...
+}: {
+  home.home = {
+    packages = [
+      (pkgs.gtimelog.overrideAttrs (oldAttrs: {
+        src = gtimelog;
+        makeWrapperArgs = [
+          "--set GI_TYPELIB_PATH ${lib.makeSearchPathOutput "lib"
+            "lib/girepository-1.0" (with pkgs; [
+              gtk3
+              libsoup
+              libsecret
+              pango
+              harfbuzz
+              gdk-pixbuf
+              atk
+            ])}"
+          "--set GIO_MODULE_DIR ${lib.makeSearchPathOutput "out"
+            "lib/gio/modules" (with pkgs; [
+              glib-networking
+            ])}"
+        ];
+        buildInputs = oldAttrs.buildInputs ++ [pkgs.glib-networking];
+      }))
+    ];
+    file.".gtimelog/gtimelogrc".source = ./gtimelog/gtimelogrc.toml;
+  };
+
+  config.environment.persistence."/nix/persist".users.${username}.directories = [".gtimelog"];
+}
diff --git a/modules/gtimelog/gtimelogrc.toml b/modules/gtimelog/gtimelogrc.toml
new file mode 100644
index 0000000..fcd85bf
--- /dev/null
+++ b/modules/gtimelog/gtimelogrc.toml
@@ -0,0 +1,19 @@
+[gtimelog]
+task_list_expiry = 1 day
+task_list_url = https://chronophage.collabora.com/tasks
+report_to_url = https://chronophage.collabora.com/timesheet
+
+edit_task_list_cmd = kitty nvim
+editor = kitty nvim
+
+virtual_midnight = 03:00
+
+hours = 8
+show_office_hours = True
+
+gtk-completion = True
+
+remind_idle = 10 minutes
+
+show_tray_icon = True
+autoarrival = True