mirror of
https://github.com/nix-community/home-manager.git
synced 2025-11-08 19:46:05 +01:00
The account password is different from the sync key needed here. Add instructions for how to get the sync key, and make the option name accurate.
348 lines
9.3 KiB
Nix
348 lines
9.3 KiB
Nix
{
|
|
lib,
|
|
config,
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
helper = import ./helper.nix { inherit lib config pkgs; };
|
|
|
|
ankiBaseDir =
|
|
if pkgs.stdenv.hostPlatform.isDarwin then
|
|
"Library/Application Support/Anki2"
|
|
else
|
|
"${config.xdg.dataHome}/Anki2";
|
|
cfg = config.programs.anki;
|
|
in
|
|
{
|
|
meta.maintainers = [ lib.maintainers.junestepp ];
|
|
|
|
imports = [
|
|
(lib.mkRenamedOptionModule
|
|
[ "programs" "anki" "sync" "passwordFile" ]
|
|
[ "programs" "anki" "sync" "keyFile" ]
|
|
)
|
|
];
|
|
|
|
options.programs.anki = {
|
|
enable = lib.mkEnableOption "Anki";
|
|
|
|
package = lib.mkPackageOption pkgs "anki" { };
|
|
|
|
language = lib.mkOption {
|
|
type = lib.types.nonEmptyStr;
|
|
default = "en_US";
|
|
example = "ja_JP";
|
|
description = ''
|
|
Display language. Should be an underscore separated language tag.
|
|
See <https://github.com/ankitects/anki/blob/main/pylib/anki/lang.py> for
|
|
supported tags.
|
|
'';
|
|
};
|
|
|
|
videoDriver = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
nullOr (enum [
|
|
"opengl"
|
|
"angle"
|
|
"software"
|
|
"metal"
|
|
"vulkan"
|
|
"d3d11"
|
|
]);
|
|
default = null;
|
|
example = "opengl";
|
|
description = "Video driver to use.";
|
|
};
|
|
|
|
theme = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
nullOr (enum [
|
|
"followSystem"
|
|
"light"
|
|
"dark"
|
|
]);
|
|
default = null;
|
|
example = "dark";
|
|
description = "Theme to use.";
|
|
};
|
|
|
|
style = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
nullOr (enum [
|
|
"anki"
|
|
"native"
|
|
]);
|
|
default = null;
|
|
example = "native";
|
|
description = "Widgets style.";
|
|
};
|
|
|
|
uiScale = lib.mkOption {
|
|
type = with lib.types; nullOr (numbers.between 0.0 1.0);
|
|
default = null;
|
|
example = 1.0;
|
|
description = "User interface scale.";
|
|
};
|
|
|
|
hideTopBar = lib.mkOption {
|
|
type = with lib.types; nullOr bool;
|
|
default = null;
|
|
example = true;
|
|
description = "Hide top bar during review.";
|
|
};
|
|
hideTopBarMode = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
nullOr (enum [
|
|
"fullscreen"
|
|
"always"
|
|
]);
|
|
default = null;
|
|
example = "fullscreen";
|
|
description = "When to hide the top bar when `hideTopBar` is enabled.";
|
|
};
|
|
|
|
hideBottomBar = lib.mkOption {
|
|
type = with lib.types; nullOr bool;
|
|
default = null;
|
|
example = true;
|
|
description = "Hide bottom bar during review.";
|
|
};
|
|
hideBottomBarMode = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
nullOr (enum [
|
|
"fullscreen"
|
|
"always"
|
|
]);
|
|
default = null;
|
|
example = "fullscreen";
|
|
description = "When to hide the bottom bar when `hideBottomBar` is enabled.";
|
|
};
|
|
|
|
reduceMotion = lib.mkOption {
|
|
type = with lib.types; nullOr bool;
|
|
default = null;
|
|
example = true;
|
|
description = "Disable various animations and transitions of the user interface.";
|
|
};
|
|
|
|
minimalistMode = lib.mkOption {
|
|
type = with lib.types; nullOr bool;
|
|
default = null;
|
|
example = true;
|
|
description = "Minimalist user interface mode.";
|
|
};
|
|
|
|
spacebarRatesCard = lib.mkOption {
|
|
type = with lib.types; nullOr bool;
|
|
default = null;
|
|
example = true;
|
|
description = "Spacebar (or enter) also answers card.";
|
|
};
|
|
|
|
legacyImportExport = lib.mkOption {
|
|
type = with lib.types; nullOr bool;
|
|
default = null;
|
|
description = "Use legacy (pre 2.1.55) import/export handling code.";
|
|
};
|
|
|
|
answerKeys = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
listOf (submodule {
|
|
options = {
|
|
ease = lib.mkOption {
|
|
type = with lib.types; int;
|
|
example = 3;
|
|
description = ''
|
|
Number associated with an answer button.
|
|
|
|
By default, 1 = Again, 2 = Hard, 3 = Good, and 4 = Easy.
|
|
'';
|
|
};
|
|
key = lib.mkOption {
|
|
type = with lib.types; str;
|
|
example = "3";
|
|
description = ''
|
|
Keyboard shortcut for this answer button. The shortcut should be in
|
|
the string format used by <https://doc.qt.io/qt-6/qkeysequence.html>.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = [ ];
|
|
example = [
|
|
{
|
|
ease = 1;
|
|
key = "left";
|
|
}
|
|
{
|
|
ease = 2;
|
|
key = "up";
|
|
}
|
|
{
|
|
ease = 3;
|
|
key = "right";
|
|
}
|
|
{
|
|
ease = 4;
|
|
key = "down";
|
|
}
|
|
];
|
|
description = ''
|
|
Overrides for choosing what keyboard shortcut activates each
|
|
answer button. The Anki default will be used for ones without an
|
|
override defined.
|
|
'';
|
|
};
|
|
|
|
sync = {
|
|
username = lib.mkOption {
|
|
type = with lib.types; nullOr str;
|
|
default = null;
|
|
example = "lovelearning@email.com";
|
|
description = "Sync account username.";
|
|
};
|
|
|
|
usernameFile = lib.mkOption {
|
|
type = with lib.types; nullOr path;
|
|
default = null;
|
|
description = "Path to a file containing the sync account username.";
|
|
};
|
|
|
|
keyFile = lib.mkOption {
|
|
type = with lib.types; nullOr path;
|
|
default = null;
|
|
description = ''
|
|
Path to a file containing the sync account sync key. This is different from
|
|
the account password.
|
|
|
|
To get the sync key, follow these steps:
|
|
|
|
- Enable this Home Manager module: `programs.anki.enable = true`
|
|
- Open Anki.
|
|
- Navigate to the sync settings page. (Tools > Preferences > Syncing)
|
|
- Log in to your AnkiWeb account.
|
|
- Select "Yes" to the prompt about saving preferences and syncing.
|
|
- A Home Manager warning prompt will show. Select "Show details...".
|
|
- Get your sync key from the message: "syncKey changed from \`None\` to \`<YOUR SYNC KEY WILL BE HERE>\`"
|
|
'';
|
|
};
|
|
|
|
url = lib.mkOption {
|
|
type = with lib.types; nullOr str;
|
|
default = null;
|
|
example = "http://example.com/anki-sync/";
|
|
description = ''
|
|
Custom sync server URL. See <https://docs.ankiweb.net/sync-server.html>.
|
|
'';
|
|
};
|
|
|
|
autoSync = lib.mkOption {
|
|
type = with lib.types; nullOr bool;
|
|
default = null;
|
|
example = true;
|
|
description = "Automatically sync on profile open/close.";
|
|
};
|
|
|
|
syncMedia = lib.mkOption {
|
|
type = with lib.types; nullOr bool;
|
|
default = null;
|
|
example = true;
|
|
description = "Synchronize audio and images too.";
|
|
};
|
|
|
|
autoSyncMediaMinutes = lib.mkOption {
|
|
type = with lib.types; nullOr ints.unsigned;
|
|
default = null;
|
|
example = 15;
|
|
description = ''
|
|
Automatically sync media every X minutes. Set this to 0 to disable
|
|
periodic media syncing.
|
|
'';
|
|
};
|
|
|
|
networkTimeout = lib.mkOption {
|
|
type = with lib.types; nullOr ints.unsigned;
|
|
default = null;
|
|
example = 60;
|
|
description = "Network timeout in seconds.";
|
|
};
|
|
};
|
|
|
|
addons = lib.mkOption {
|
|
type = with lib.types; listOf package;
|
|
default = [ ];
|
|
example = lib.literalExpression ''
|
|
[
|
|
# When the add-on is already available in nixpkgs
|
|
pkgs.ankiAddons.anki-connect
|
|
|
|
# When the add-on is not available in nixpkgs
|
|
(pkgs.anki-utils.buildAnkiAddon (finalAttrs: {
|
|
pname = "recolor";
|
|
version = "3.1";
|
|
src = pkgs.fetchFromGitHub {
|
|
owner = "AnKing-VIP";
|
|
repo = "AnkiRecolor";
|
|
rev = finalAttrs.version;
|
|
sparseCheckout = [ "src/addon" ];
|
|
hash = "sha256-28DJq2l9DP8O6OsbNQCZ0pm4S6CQ3Yz0Vfvlj+iQw8Y=";
|
|
};
|
|
sourceRoot = "''${finalAttrs.src.name}/src/addon";
|
|
}))
|
|
|
|
# When the add-on needs to be configured
|
|
pkgs.ankiAddons.passfail2.withConfig {
|
|
config = {
|
|
again_button_name = "not quite";
|
|
good_button_name = "excellent";
|
|
toggle_names_textcolors = 1;
|
|
};
|
|
user_files = ./dir-to-be-merged-into-addon-user-files-dir;
|
|
};
|
|
]
|
|
'';
|
|
description = "List of Anki add-on packages to install.";
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
assertions = [
|
|
{
|
|
assertion = !(cfg.sync.username != null && cfg.sync.usernameFile != null);
|
|
message = ''
|
|
The `programs.anki.sync` `username` option is mutually exclusive with
|
|
the `usernameFile` option.
|
|
'';
|
|
}
|
|
{
|
|
assertion = cfg.package ? withAddons;
|
|
message = ''
|
|
The value of `programs.anki.package` doesn't support declaratively managing
|
|
add-ons. Make sure you are using `pkgs.anki`.
|
|
'';
|
|
}
|
|
];
|
|
|
|
home.packages = [
|
|
(cfg.package.withAddons (
|
|
[
|
|
helper.homeManagerAnkiAddon
|
|
helper.syncConfigAnkiAddon
|
|
]
|
|
++ cfg.addons
|
|
))
|
|
];
|
|
|
|
home.file."${ankiBaseDir}/gldriver6" = lib.mkIf (cfg.videoDriver != null) {
|
|
source = "${helper.ankiConfig}/gldriver6";
|
|
};
|
|
home.file."${ankiBaseDir}/prefs21.db".source = "${helper.ankiConfig}/prefs21.db";
|
|
};
|
|
}
|