diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 3e110bf50..a4c476a12 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -138,6 +138,7 @@ Monty Evans Nil Admirari Michael Winkworth Mateusz Wojewoda +Jarrett Ye ******************** diff --git a/Cargo.lock b/Cargo.lock index 04a005a95..a6400648b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,7 +107,7 @@ dependencies = [ "fluent", "fluent-bundle", "fnv", - "fsrs-optimizer", + "fsrs", "futures", "hex", "htmlescape", @@ -574,8 +574,8 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "burn" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "burn-core", "burn-train", @@ -583,8 +583,8 @@ dependencies = [ [[package]] name = "burn-autodiff" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "burn-common", "burn-tensor", @@ -595,8 +595,8 @@ dependencies = [ [[package]] name = "burn-common" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "const-random", "rand 0.8.5", @@ -606,8 +606,8 @@ dependencies = [ [[package]] name = "burn-core" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "bincode", "burn-autodiff", @@ -631,8 +631,8 @@ dependencies = [ [[package]] name = "burn-dataset" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "csv 1.2.2", "derive-new", @@ -651,8 +651,8 @@ dependencies = [ [[package]] name = "burn-derive" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "derive-new", "proc-macro2", @@ -662,8 +662,8 @@ dependencies = [ [[package]] name = "burn-ndarray" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "burn-autodiff", "burn-common", @@ -680,8 +680,8 @@ dependencies = [ [[package]] name = "burn-tensor" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "burn-tensor-testgen", "derive-new", @@ -696,8 +696,8 @@ dependencies = [ [[package]] name = "burn-tensor-testgen" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "proc-macro2", "quote", @@ -706,8 +706,8 @@ dependencies = [ [[package]] name = "burn-train" -version = "0.9.0" -source = "git+https://github.com/burn-rs/burn.git?rev=36446e8d35694a9158f97e85e44b84544b8c4afb#36446e8d35694a9158f97e85e44b84544b8c4afb" +version = "0.10.0" +source = "git+https://github.com/burn-rs/burn.git?rev=e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c#e7a65e24c4e88110f2bf6b3a29ac456a12c2ca0c" dependencies = [ "burn-core", "derive-new", @@ -1365,9 +1365,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "faster-hex" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9042d281a5eec0f2387f8c3ea6c4514e2cf2732c90a85aaf383b761ee3b290d" +checksum = "239f7bfb930f820ab16a9cd95afc26f88264cf6905c960b340a615384aa3338a" dependencies = [ "serde", ] @@ -1530,9 +1530,9 @@ dependencies = [ ] [[package]] -name = "fsrs-optimizer" +name = "fsrs" version = "0.1.0" -source = "git+https://github.com/open-spaced-repetition/fsrs-optimizer-rs?rev=e0b15cce555a94de6fdaa4bf1e096d19704a397d#e0b15cce555a94de6fdaa4bf1e096d19704a397d" +source = "git+https://github.com/open-spaced-repetition/fsrs-rs.git?rev=bae680bfde996f614741b32ac63a27a1a882a45b#bae680bfde996f614741b32ac63a27a1a882a45b" dependencies = [ "burn", "itertools 0.11.0", diff --git a/Cargo.toml b/Cargo.toml index ae53a4847..cfd804a0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,23 @@ members = [ exclude = ["qt/bundle"] resolver = "2" +[workspace.dependencies.csv] +git = "https://github.com/ankitects/rust-csv.git" +rev = "1c9d3aab6f79a7d815c69f925a46a4590c115f90" + +[workspace.dependencies.percent-encoding-iri] +git = "https://github.com/ankitects/rust-url.git" +rev = "bb930b8d089f4d30d7d19c12e54e66191de47b88" + +[workspace.dependencies.linkcheck] +git = "https://github.com/ankitects/linkcheck.git" +rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca" + +[workspace.dependencies.fsrs] +git = "https://github.com/open-spaced-repetition/fsrs-rs.git" +rev = "bae680bfde996f614741b32ac63a27a1a882a45b" +# path = "../../../fsrs-rs" + [workspace.dependencies] # local anki = { path = "rslib" } @@ -36,14 +53,6 @@ anki_process = { path = "rslib/process" } anki_proto_gen = { path = "rslib/proto_gen" } ninja_gen = { "path" = "build/ninja_gen" } -fsrs-optimizer = { git = "https://github.com/open-spaced-repetition/fsrs-optimizer-rs", rev = "e0b15cce555a94de6fdaa4bf1e096d19704a397d" } -# fsrs-optimizer.path = "../../../fsrs-optimizer-rs" - -# forked -csv = { git = "https://github.com/ankitects/rust-csv.git", rev = "1c9d3aab6f79a7d815c69f925a46a4590c115f90" } -percent-encoding-iri = { git = "https://github.com/ankitects/rust-url.git", rev = "bb930b8d089f4d30d7d19c12e54e66191de47b88" } -linkcheck = { git = "https://github.com/ankitects/linkcheck.git", rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca" } - # pinned unicase = "=2.6.0" # any changes could invalidate sqlite indexes diff --git a/cargo/licenses.json b/cargo/licenses.json index c9ef69734..6f7a4b5fb 100644 --- a/cargo/licenses.json +++ b/cargo/licenses.json @@ -334,7 +334,7 @@ }, { "name": "burn", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn", "license": "Apache-2.0 OR MIT", @@ -343,7 +343,7 @@ }, { "name": "burn-autodiff", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn/tree/main/burn-autodiff", "license": "Apache-2.0 OR MIT", @@ -352,7 +352,7 @@ }, { "name": "burn-common", - "version": "0.9.0", + "version": "0.10.0", "authors": "Dilshod Tadjibaev (@antimora)", "repository": "https://github.com/burn-rs/burn/tree/main/burn-common", "license": "Apache-2.0 OR MIT", @@ -361,7 +361,7 @@ }, { "name": "burn-core", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn/tree/main/burn-core", "license": "Apache-2.0 OR MIT", @@ -370,7 +370,7 @@ }, { "name": "burn-dataset", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn/tree/main/burn-dataset", "license": "Apache-2.0 OR MIT", @@ -379,7 +379,7 @@ }, { "name": "burn-derive", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn/tree/main/burn-derive", "license": "Apache-2.0 OR MIT", @@ -388,7 +388,7 @@ }, { "name": "burn-ndarray", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn/tree/main/burn-ndarray", "license": "Apache-2.0 OR MIT", @@ -397,7 +397,7 @@ }, { "name": "burn-tensor", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn/tree/main/burn-tensor", "license": "Apache-2.0 OR MIT", @@ -406,7 +406,7 @@ }, { "name": "burn-tensor-testgen", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn/tree/main/burn-tensor-testgen", "license": "Apache-2.0 OR MIT", @@ -415,7 +415,7 @@ }, { "name": "burn-train", - "version": "0.9.0", + "version": "0.10.0", "authors": "nathanielsimard ", "repository": "https://github.com/burn-rs/burn/tree/main/burn-train", "license": "Apache-2.0 OR MIT", @@ -847,7 +847,7 @@ }, { "name": "faster-hex", - "version": "0.8.0", + "version": "0.8.1", "authors": "zhangsoledad <787953403@qq.com>", "repository": "https://github.com/NervosFoundation/faster-hex", "license": "MIT", @@ -972,7 +972,7 @@ "description": "Parser for values from the Forwarded header (RFC 7239)" }, { - "name": "fsrs-optimizer", + "name": "fsrs", "version": "0.1.0", "authors": null, "repository": null, diff --git a/ftl/core/card-stats.ftl b/ftl/core/card-stats.ftl index 30cc81027..37d7736d5 100644 --- a/ftl/core/card-stats.ftl +++ b/ftl/core/card-stats.ftl @@ -24,6 +24,9 @@ card-stats-review-log-type-filtered = Filtered card-stats-review-log-type-manual = Manual card-stats-no-card = (No card to display.) card-stats-custom-data = Custom Data +card-stats-fsrs-stability = Stability +card-stats-fsrs-difficulty = Difficulty +card-stats-fsrs-retrievability = Retrievability ## Window Titles diff --git a/ftl/core/deck-config.ftl b/ftl/core/deck-config.ftl index a0a9b7dde..088ac79bf 100644 --- a/ftl/core/deck-config.ftl +++ b/ftl/core/deck-config.ftl @@ -307,6 +307,26 @@ deck-config-maximum-answer-secs-above-recommended = Anki can schedule your revie deck-config-which-deck = Which deck would you like to display options for? +## Messages related to the FSRS scheduler + +deck-config-updating-cards = Updating cards: { $current_cards_count }/{ $total_cards_count }... +deck-config-invalid-weights = Weights must be either left blank to use the defaults, or must be 17 comma-separated numbers. +deck-config-not-enough-history = Insufficient review history to perform this operation. +deck-config-limited-history = + { $count -> + [one] Only { $count } review was found. + *[other] Only { $count } reviews were found. + } The custom weights are likely to be inaccurate, and using the defaults instead is recommended. +deck-config-compute-weights-search = Search; leave blank for all cards using this preset +# Numbers that control how aggressively the FSRS algorithm schedules cards +deck-config-weights = Model weights +deck-config-compute-optimal-weights = Compute optimal weights +deck-config-compute-optimal-retention = Compute optimal retention +deck-config-compute-button = Compute +deck-config-analyze-button = Analyze +deck-config-desired-retention = Desired retention +deck-config-smaller-is-better = Smaller numbers indicate better memory estimates. +deck-config-steps-too-large-for-fsrs = When FSRS is enabled, interday (re)learning steps are not recommended. ## NO NEED TO TRANSLATE. This text is no longer used by Anki, and will be removed in the future. diff --git a/ftl/core/statistics.ftl b/ftl/core/statistics.ftl index 847902191..b369741c0 100644 --- a/ftl/core/statistics.ftl +++ b/ftl/core/statistics.ftl @@ -93,13 +93,27 @@ statistics-range-deck = deck statistics-range-collection = collection statistics-range-search = Search statistics-card-ease-title = Card Ease +statistics-card-difficulty-title = Card Difficulty +statistics-card-retrievability-title = Card Retrievability statistics-card-ease-subtitle = The lower the ease, the more frequently a card will appear. +statistics-card-difficulty-subtitle = The higher the difficulty, the more frequently a card will appear. +statistics-retrievability-subtitle = How likely you are to remember. # eg "3 cards with 150-170% ease" statistics-card-ease-tooltip = { $cards -> [one] { $cards } card with { $percent } ease *[other] { $cards } cards with { $percent } ease } +statistics-card-difficulty-tooltip = + { $cards -> + [one] { $cards } card with { $percent } difficulty + *[other] { $cards } cards with { $percent } difficulty + } +statistics-retrievability-tooltip = + { $cards -> + [one] { $cards } card with { $percent } retrievability + *[other] { $cards } cards with { $percent } retrievability + } statistics-future-due-title = Future Due statistics-future-due-subtitle = The number of reviews due in the future. statistics-added-title = Added @@ -200,6 +214,8 @@ statistics-cards-per-day = *[other] { $count } cards/day } statistics-average-ease = Average ease +statistics-average-difficulty = Average difficulty +statistics-average-retrievability = Average retrievability statistics-save-pdf = Save PDF statistics-saved = Saved. statistics-stats = stats diff --git a/proto/anki/cards.proto b/proto/anki/cards.proto index 0b4b9354e..e0f41f12c 100644 --- a/proto/anki/cards.proto +++ b/proto/anki/cards.proto @@ -49,9 +49,15 @@ message Card { int64 original_deck_id = 16; uint32 flags = 17; optional uint32 original_position = 18; + optional FsrsMemoryState fsrs_memory_state = 20; string custom_data = 19; } +message FsrsMemoryState { + float stability = 1; + float difficulty = 2; +} + message UpdateCardsRequest { repeated Card cards = 1; bool skip_undo_entry = 2; diff --git a/proto/anki/collection.proto b/proto/anki/collection.proto index 6d78cd35b..84863cbef 100644 --- a/proto/anki/collection.proto +++ b/proto/anki/collection.proto @@ -118,17 +118,6 @@ message Progress { uint32 stage_current = 3; } - message ComputeWeights { - uint32 current = 1; - uint32 total = 2; - uint32 revlog_entries = 3; - } - - message ComputeRetention { - uint32 current = 1; - uint32 total = 2; - } - oneof value { generic.Empty none = 1; sync.MediaSyncProgress media_sync = 2; @@ -138,11 +127,29 @@ message Progress { DatabaseCheck database_check = 6; string importing = 7; string exporting = 8; - ComputeWeights compute_weights = 9; - ComputeRetention compute_retention = 10; + ComputeWeightsProgress compute_weights = 9; + ComputeRetentionProgress compute_retention = 10; + ComputeMemoryProgress compute_memory = 11; } } +message ComputeWeightsProgress { + uint32 current = 1; + uint32 total = 2; + uint32 fsrs_items = 3; +} + +message ComputeRetentionProgress { + uint32 current = 1; + uint32 total = 2; +} + +message ComputeMemoryProgress { + uint32 current_cards = 1; + uint32 total_cards = 2; + string label = 3; +} + message CreateBackupRequest { string backup_folder = 1; // Create a backup even if the configured interval hasn't elapsed yet. diff --git a/proto/anki/scheduler.proto b/proto/anki/scheduler.proto index e279d2dd1..d26ebad31 100644 --- a/proto/anki/scheduler.proto +++ b/proto/anki/scheduler.proto @@ -63,6 +63,7 @@ message SchedulingState { message Learning { uint32 remaining_steps = 1; uint32 scheduled_secs = 2; + optional cards.FsrsMemoryState fsrs_memory_state = 6; } message Review { uint32 scheduled_days = 1; @@ -70,6 +71,7 @@ message SchedulingState { float ease_factor = 3; uint32 lapses = 4; bool leeched = 5; + optional cards.FsrsMemoryState fsrs_memory_state = 6; } message Relearning { Review review = 1; @@ -330,6 +332,8 @@ message ComputeFsrsWeightsRequest { message ComputeFsrsWeightsResponse { repeated float weights = 1; + // if less than 1000, should warn user + uint32 fsrs_items = 2; } message ComputeOptimalRetentionRequest { @@ -338,9 +342,18 @@ message ComputeOptimalRetentionRequest { uint32 days_to_simulate = 3; uint32 max_seconds_of_study_per_day = 4; uint32 max_interval = 5; - uint32 recall_secs = 6; - uint32 forget_secs = 7; - uint32 learn_secs = 8; + double recall_secs_hard = 6; + double recall_secs_good = 7; + double recall_secs_easy = 8; + uint32 forget_secs = 9; + uint32 learn_secs = 10; + double first_rating_probability_again = 11; + double first_rating_probability_hard = 12; + double first_rating_probability_good = 13; + double first_rating_probability_easy = 14; + double review_rating_probability_hard = 15; + double review_rating_probability_good = 16; + double review_rating_probability_easy = 17; } message ComputeOptimalRetentionResponse { @@ -354,5 +367,5 @@ message EvaluateWeightsRequest { message EvaluateWeightsResponse { float log_loss = 1; - float rmse = 2; + float rmse_bins = 2; } diff --git a/proto/anki/stats.proto b/proto/anki/stats.proto index 8131eba1c..4a4301a5d 100644 --- a/proto/anki/stats.proto +++ b/proto/anki/stats.proto @@ -52,7 +52,10 @@ message CardStatsResponse { float total_secs = 15; string card_type = 16; string notetype = 17; - string custom_data = 18; + optional cards.FsrsMemoryState fsrs_memory_state = 18; + // not set if due date/state not available + optional float fsrs_retrievability = 19; + string custom_data = 20; } message GraphsRequest { @@ -70,6 +73,9 @@ message GraphsResponse { message Eases { map eases = 1; } + message Retrievability { + map retrievability = 1; + } message FutureDue { map future_due = 1; bool have_backlog = 2; @@ -141,11 +147,13 @@ message GraphsResponse { Hours hours = 3; Today today = 4; Eases eases = 5; + Eases difficulty = 11; Intervals intervals = 6; FutureDue future_due = 7; Added added = 8; ReviewCountsAndTimes reviews = 9; uint32 rollover_hour = 10; + Retrievability retrievability = 12; } message GraphPreferences { diff --git a/pylib/anki/cards.py b/pylib/anki/cards.py index 56b83e788..43e74f6e8 100644 --- a/pylib/anki/cards.py +++ b/pylib/anki/cards.py @@ -32,6 +32,7 @@ from anki.sound import AVTag # types CardId = NewType("CardId", int) BackendCard = cards_pb2.Card +FSRSMemoryState = cards_pb2.FsrsMemoryState class Card(DeprecatedNamesMixin): @@ -44,6 +45,7 @@ class Card(DeprecatedNamesMixin): odid: anki.decks.DeckId queue: CardQueue type: CardType + fsrs_memory_state: FSRSMemoryState | None def __init__( self, @@ -93,6 +95,9 @@ class Card(DeprecatedNamesMixin): card.original_position if card.HasField("original_position") else None ) self.custom_data = card.custom_data + self.fsrs_memory_state = ( + card.fsrs_memory_state if card.HasField("fsrs_memory_state") else None + ) def _to_backend_card(self) -> cards_pb2.Card: # mtime & usn are set by backend @@ -114,6 +119,7 @@ class Card(DeprecatedNamesMixin): flags=self.flags, original_position=self.original_position, custom_data=self.custom_data, + fsrs_memory_state=self.fsrs_memory_state, ) def flush(self) -> None: diff --git a/qt/aqt/about.py b/qt/aqt/about.py index 877b4a08e..41be7d4a3 100644 --- a/qt/aqt/about.py +++ b/qt/aqt/about.py @@ -232,6 +232,7 @@ def show(mw: aqt.AnkiQt) -> QDialog: "Edgar Benavent CatalĂ ", "Kieran Black", "Mateusz Wojewoda", + "Jarrett Ye", ) ) diff --git a/qt/aqt/deckbrowser.py b/qt/aqt/deckbrowser.py index 2018c8675..80a2e13b4 100644 --- a/qt/aqt/deckbrowser.py +++ b/qt/aqt/deckbrowser.py @@ -61,7 +61,6 @@ class DeckBrowser: self.web = mw.web self.bottom = BottomBar(mw, mw.bottomWeb) self.scrollPos = QPoint(0, 0) - self._v1_message_dismissed_at = 0 self._refresh_needed = False def show(self) -> None: @@ -116,7 +115,10 @@ class DeckBrowser: elif cmd == "v2upgrade": self._confirm_upgrade() elif cmd == "v2upgradeinfo": - openLink("https://faqs.ankiweb.net/the-anki-2.1-scheduler.html") + if self.mw.col.sched_ver() == 1: + openLink("https://faqs.ankiweb.net/the-anki-2.1-scheduler.html") + else: + openLink("https://faqs.ankiweb.net/the-2021-scheduler.html") elif cmd == "select": set_current_deck( parent=self.mw, deck_id=DeckId(int(arg)) @@ -365,14 +367,16 @@ class DeckBrowser: ###################################################################### def _v1_upgrade_message(self) -> str: - if self.mw.col.sched_ver() == 2: + if self.mw.col.sched_ver() == 2 and self.mw.col.v3_scheduler(): return "" + update_required = tr.scheduling_update_required().replace("V2", "v3") + return f"""
- {tr.scheduling_update_required()} + {update_required}