mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
merge the filtered deck errors into an enum
Fixes the wrong message being shown when trying to move cards to a filtered deck
This commit is contained in:
parent
7df128a103
commit
ac1b9fadde
8 changed files with 53 additions and 25 deletions
|
@ -50,18 +50,14 @@ class ExistsError(Exception):
|
||||||
|
|
||||||
|
|
||||||
class DeckRenameError(Exception):
|
class DeckRenameError(Exception):
|
||||||
"""Legacy error, use DeckIsFilteredError instead."""
|
"""Legacy error, use FilteredDeckError instead."""
|
||||||
|
|
||||||
def __init__(self, description: str, *args: object) -> None:
|
def __init__(self, description: str, *args: object) -> None:
|
||||||
super().__init__(description, *args)
|
super().__init__(description, *args)
|
||||||
self.description = description
|
self.description = description
|
||||||
|
|
||||||
|
|
||||||
class DeckIsFilteredError(StringError, DeckRenameError):
|
class FilteredDeckError(StringError, DeckRenameError):
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class FilteredDeckEmpty(StringError):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,10 +91,8 @@ def backend_exception_to_pylib(err: _pb.BackendError) -> Exception:
|
||||||
return NotFoundError()
|
return NotFoundError()
|
||||||
elif val == "exists":
|
elif val == "exists":
|
||||||
return ExistsError()
|
return ExistsError()
|
||||||
elif val == "deck_is_filtered":
|
elif val == "filtered_deck_error":
|
||||||
return DeckIsFilteredError(err.localized)
|
return FilteredDeckError(err.localized)
|
||||||
elif val == "filtered_deck_empty":
|
|
||||||
return FilteredDeckEmpty(err.localized)
|
|
||||||
elif val == "proto_error":
|
elif val == "proto_error":
|
||||||
return StringError(err.localized)
|
return StringError(err.localized)
|
||||||
elif val == "search_error":
|
elif val == "search_error":
|
||||||
|
|
|
@ -568,9 +568,8 @@ message BackendError {
|
||||||
string proto_error = 10;
|
string proto_error = 10;
|
||||||
Empty not_found_error = 11;
|
Empty not_found_error = 11;
|
||||||
Empty exists = 12;
|
Empty exists = 12;
|
||||||
Empty deck_is_filtered = 13;
|
Empty filtered_deck_error = 13;
|
||||||
Empty filtered_deck_empty = 14;
|
Empty search_error = 14;
|
||||||
Empty search_error = 15;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,10 @@ pub(super) fn anki_error_to_proto_error(err: AnkiError, tr: &I18n) -> pb::Backen
|
||||||
AnkiError::ProtoError(info) => V::ProtoError(info),
|
AnkiError::ProtoError(info) => V::ProtoError(info),
|
||||||
AnkiError::NotFound => V::NotFoundError(pb::Empty {}),
|
AnkiError::NotFound => V::NotFoundError(pb::Empty {}),
|
||||||
AnkiError::Existing => V::Exists(pb::Empty {}),
|
AnkiError::Existing => V::Exists(pb::Empty {}),
|
||||||
AnkiError::DeckIsFiltered => V::DeckIsFiltered(pb::Empty {}),
|
AnkiError::FilteredDeckError(_) => V::FilteredDeckError(pb::Empty {}),
|
||||||
AnkiError::SearchError(_) => V::SearchError(pb::Empty {}),
|
AnkiError::SearchError(_) => V::SearchError(pb::Empty {}),
|
||||||
AnkiError::TemplateSaveError { .. } => V::TemplateParse(pb::Empty {}),
|
AnkiError::TemplateSaveError { .. } => V::TemplateParse(pb::Empty {}),
|
||||||
AnkiError::ParseNumError => V::InvalidInput(pb::Empty {}),
|
AnkiError::ParseNumError => V::InvalidInput(pb::Empty {}),
|
||||||
AnkiError::FilteredDeckEmpty => V::FilteredDeckEmpty(pb::Empty {}),
|
|
||||||
AnkiError::InvalidRegex(_) => V::InvalidInput(pb::Empty {}),
|
AnkiError::InvalidRegex(_) => V::InvalidInput(pb::Empty {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
pub(crate) mod undo;
|
pub(crate) mod undo;
|
||||||
|
|
||||||
use crate::error::{AnkiError, Result};
|
use crate::error::{AnkiError, FilteredDeckError, Result};
|
||||||
use crate::notes::NoteId;
|
use crate::notes::NoteId;
|
||||||
use crate::{
|
use crate::{
|
||||||
collection::Collection, config::SchedulerVersion, prelude::*, timestamp::TimestampSecs,
|
collection::Collection, config::SchedulerVersion, prelude::*, timestamp::TimestampSecs,
|
||||||
|
@ -234,7 +234,7 @@ impl Collection {
|
||||||
pub fn set_deck(&mut self, cards: &[CardId], deck_id: DeckId) -> Result<OpOutput<()>> {
|
pub fn set_deck(&mut self, cards: &[CardId], deck_id: DeckId) -> Result<OpOutput<()>> {
|
||||||
let deck = self.get_deck(deck_id)?.ok_or(AnkiError::NotFound)?;
|
let deck = self.get_deck(deck_id)?.ok_or(AnkiError::NotFound)?;
|
||||||
if deck.is_filtered() {
|
if deck.is_filtered() {
|
||||||
return Err(AnkiError::DeckIsFiltered);
|
return Err(FilteredDeckError::CanNotMoveCardsInto.into());
|
||||||
}
|
}
|
||||||
self.storage.set_search_table_to_card_ids(cards, false)?;
|
self.storage.set_search_table_to_card_ids(cards, false)?;
|
||||||
let sched = self.scheduler_version();
|
let sched = self.scheduler_version();
|
||||||
|
|
|
@ -12,14 +12,17 @@ pub use crate::backend_proto::{
|
||||||
filtered_deck::{search_term::Order as FilteredSearchOrder, SearchTerm as FilteredSearchTerm},
|
filtered_deck::{search_term::Order as FilteredSearchOrder, SearchTerm as FilteredSearchTerm},
|
||||||
Deck as DeckProto, DeckCommon, DeckKind as DeckKindProto, FilteredDeck, NormalDeck,
|
Deck as DeckProto, DeckCommon, DeckKind as DeckKindProto, FilteredDeck, NormalDeck,
|
||||||
};
|
};
|
||||||
use crate::{backend_proto as pb, markdown::render_markdown, text::sanitize_html_no_images};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
backend_proto as pb,
|
||||||
collection::Collection,
|
collection::Collection,
|
||||||
deckconf::DeckConfId,
|
deckconf::DeckConfId,
|
||||||
define_newtype,
|
define_newtype,
|
||||||
|
error::FilteredDeckError,
|
||||||
error::{AnkiError, Result},
|
error::{AnkiError, Result},
|
||||||
|
markdown::render_markdown,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
text::normalize_to_nfc,
|
text::normalize_to_nfc,
|
||||||
|
text::sanitize_html_no_images,
|
||||||
timestamp::TimestampSecs,
|
timestamp::TimestampSecs,
|
||||||
types::Usn,
|
types::Usn,
|
||||||
};
|
};
|
||||||
|
@ -421,7 +424,7 @@ impl Collection {
|
||||||
let child_split: Vec<_> = deck.name.split('\x1f').collect();
|
let child_split: Vec<_> = deck.name.split('\x1f').collect();
|
||||||
if let Some(parent_deck) = self.first_existing_parent(&deck.name, 0)? {
|
if let Some(parent_deck) = self.first_existing_parent(&deck.name, 0)? {
|
||||||
if parent_deck.is_filtered() {
|
if parent_deck.is_filtered() {
|
||||||
return Err(AnkiError::DeckIsFiltered);
|
return Err(FilteredDeckError::MustBeLeafNode.into());
|
||||||
}
|
}
|
||||||
let parent_count = parent_deck.name.matches('\x1f').count() + 1;
|
let parent_count = parent_deck.name.matches('\x1f').count() + 1;
|
||||||
let need_create = parent_count != child_split.len() - 1;
|
let need_create = parent_count != child_split.len() - 1;
|
||||||
|
@ -654,7 +657,7 @@ impl Collection {
|
||||||
if let Some(target) = new_parent {
|
if let Some(target) = new_parent {
|
||||||
if let Some(target) = self.storage.get_deck(target)? {
|
if let Some(target) = self.storage.get_deck(target)? {
|
||||||
if target.is_filtered() {
|
if target.is_filtered() {
|
||||||
return Err(AnkiError::DeckIsFiltered);
|
return Err(FilteredDeckError::MustBeLeafNode.into());
|
||||||
}
|
}
|
||||||
target_deck = target;
|
target_deck = target;
|
||||||
target_name = Some(target_deck.name.as_str());
|
target_name = Some(target_deck.name.as_str());
|
||||||
|
|
32
rslib/src/error/filtered.rs
Normal file
32
rslib/src/error/filtered.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
use anki_i18n::I18n;
|
||||||
|
|
||||||
|
use super::AnkiError;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum FilteredDeckError {
|
||||||
|
MustBeLeafNode,
|
||||||
|
CanNotMoveCardsInto,
|
||||||
|
SearchReturnedNoCards,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FilteredDeckError {
|
||||||
|
pub fn localized_description(&self, tr: &I18n) -> String {
|
||||||
|
match self {
|
||||||
|
FilteredDeckError::MustBeLeafNode => tr.errors_filtered_parent_deck(),
|
||||||
|
FilteredDeckError::CanNotMoveCardsInto => {
|
||||||
|
tr.browsing_cards_cant_be_manually_moved_into()
|
||||||
|
}
|
||||||
|
FilteredDeckError::SearchReturnedNoCards => tr.decks_filtered_deck_search_empty(),
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FilteredDeckError> for AnkiError {
|
||||||
|
fn from(e: FilteredDeckError) -> Self {
|
||||||
|
AnkiError::FilteredDeckError(e)
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,13 @@
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
mod db;
|
mod db;
|
||||||
|
mod filtered;
|
||||||
mod network;
|
mod network;
|
||||||
mod search;
|
mod search;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
db::{DbError, DbErrorKind},
|
db::{DbError, DbErrorKind},
|
||||||
|
filtered::FilteredDeckError,
|
||||||
network::{NetworkError, NetworkErrorKind, SyncError, SyncErrorKind},
|
network::{NetworkError, NetworkErrorKind, SyncError, SyncErrorKind},
|
||||||
search::{ParseError, SearchErrorKind},
|
search::{ParseError, SearchErrorKind},
|
||||||
};
|
};
|
||||||
|
@ -34,9 +36,8 @@ pub enum AnkiError {
|
||||||
CollectionAlreadyOpen,
|
CollectionAlreadyOpen,
|
||||||
NotFound,
|
NotFound,
|
||||||
Existing,
|
Existing,
|
||||||
DeckIsFiltered,
|
FilteredDeckError(FilteredDeckError),
|
||||||
SearchError(SearchErrorKind),
|
SearchError(SearchErrorKind),
|
||||||
FilteredDeckEmpty,
|
|
||||||
InvalidRegex(String),
|
InvalidRegex(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +74,7 @@ impl AnkiError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnkiError::ParseNumError => tr.errors_parse_number_fail().into(),
|
AnkiError::ParseNumError => tr.errors_parse_number_fail().into(),
|
||||||
AnkiError::DeckIsFiltered => tr.errors_filtered_parent_deck().into(),
|
AnkiError::FilteredDeckError(err) => err.localized_description(tr),
|
||||||
AnkiError::FilteredDeckEmpty => tr.decks_filtered_deck_search_empty().into(),
|
|
||||||
_ => format!("{:?}", self),
|
_ => format!("{:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::convert::{TryFrom, TryInto};
|
||||||
use crate::{
|
use crate::{
|
||||||
config::ConfigKey,
|
config::ConfigKey,
|
||||||
decks::{human_deck_name_to_native, FilteredDeck, FilteredSearchTerm},
|
decks::{human_deck_name_to_native, FilteredDeck, FilteredSearchTerm},
|
||||||
|
error::FilteredDeckError,
|
||||||
search::writer::{deck_search, normalize_search},
|
search::writer::{deck_search, normalize_search},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -176,7 +177,7 @@ impl Collection {
|
||||||
|
|
||||||
// if it failed to match any cards, we revert the changes
|
// if it failed to match any cards, we revert the changes
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
Err(AnkiError::FilteredDeckEmpty)
|
Err(FilteredDeckError::SearchReturnedNoCards.into())
|
||||||
} else {
|
} else {
|
||||||
// update current deck and return id
|
// update current deck and return id
|
||||||
self.set_config(ConfigKey::CurrentDeckId, &deck.id)?;
|
self.set_config(ConfigKey::CurrentDeckId, &deck.id)?;
|
||||||
|
|
Loading…
Reference in a new issue