split out cards and collection

This commit is contained in:
Damien Elmes 2021-07-10 19:52:31 +10:00
parent 616db33c0e
commit 18851ace47
16 changed files with 287 additions and 246 deletions

View file

@ -6,6 +6,8 @@ syntax = "proto3";
package anki.backend; package anki.backend;
import "anki/generic.proto"; import "anki/generic.proto";
import "anki/cards.proto";
import "anki/collection.proto";
// IDs used in RPC calls // IDs used in RPC calls
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -22,14 +24,6 @@ message NoteIds {
repeated int64 note_ids = 1; repeated int64 note_ids = 1;
} }
message CardId {
int64 cid = 1;
}
message CardIds {
repeated int64 cids = 1;
}
message DeckId { message DeckId {
int64 did = 1; int64 did = 1;
} }
@ -74,45 +68,49 @@ service SchedulingService {
rpc ExtendLimits(ExtendLimitsRequest) returns (generic.Empty); rpc ExtendLimits(ExtendLimitsRequest) returns (generic.Empty);
rpc CountsForDeckToday(DeckId) returns (CountsForDeckTodayResponse); rpc CountsForDeckToday(DeckId) returns (CountsForDeckTodayResponse);
rpc CongratsInfo(generic.Empty) returns (CongratsInfoResponse); rpc CongratsInfo(generic.Empty) returns (CongratsInfoResponse);
rpc RestoreBuriedAndSuspendedCards(CardIds) returns (OpChanges); rpc RestoreBuriedAndSuspendedCards(cards.CardIds)
rpc UnburyDeck(UnburyDeckRequest) returns (OpChanges); returns (collection.OpChanges);
rpc UnburyDeck(UnburyDeckRequest) returns (collection.OpChanges);
rpc BuryOrSuspendCards(BuryOrSuspendCardsRequest) rpc BuryOrSuspendCards(BuryOrSuspendCardsRequest)
returns (OpChangesWithCount); returns (collection.OpChangesWithCount);
rpc EmptyFilteredDeck(DeckId) returns (OpChanges); rpc EmptyFilteredDeck(DeckId) returns (collection.OpChanges);
rpc RebuildFilteredDeck(DeckId) returns (OpChangesWithCount); rpc RebuildFilteredDeck(DeckId) returns (collection.OpChangesWithCount);
rpc ScheduleCardsAsNew(ScheduleCardsAsNewRequest) returns (OpChanges); rpc ScheduleCardsAsNew(ScheduleCardsAsNewRequest)
rpc SetDueDate(SetDueDateRequest) returns (OpChanges); returns (collection.OpChanges);
rpc SortCards(SortCardsRequest) returns (OpChangesWithCount); rpc SetDueDate(SetDueDateRequest) returns (collection.OpChanges);
rpc SortDeck(SortDeckRequest) returns (OpChangesWithCount); rpc SortCards(SortCardsRequest) returns (collection.OpChangesWithCount);
rpc GetNextCardStates(CardId) returns (NextCardStates); rpc SortDeck(SortDeckRequest) returns (collection.OpChangesWithCount);
rpc GetNextCardStates(cards.CardId) returns (NextCardStates);
rpc DescribeNextStates(NextCardStates) returns (generic.StringList); rpc DescribeNextStates(NextCardStates) returns (generic.StringList);
rpc StateIsLeech(SchedulingState) returns (generic.Bool); rpc StateIsLeech(SchedulingState) returns (generic.Bool);
rpc AnswerCard(CardAnswer) returns (OpChanges); rpc AnswerCard(CardAnswer) returns (collection.OpChanges);
rpc UpgradeScheduler(generic.Empty) returns (generic.Empty); rpc UpgradeScheduler(generic.Empty) returns (generic.Empty);
rpc GetQueuedCards(GetQueuedCardsRequest) returns (QueuedCards); rpc GetQueuedCards(GetQueuedCardsRequest) returns (QueuedCards);
} }
service DecksService { service DecksService {
rpc AddDeckLegacy(generic.Json) returns (OpChangesWithId); rpc AddDeckLegacy(generic.Json) returns (collection.OpChangesWithId);
rpc AddOrUpdateDeckLegacy(AddOrUpdateDeckLegacyRequest) returns (DeckId); rpc AddOrUpdateDeckLegacy(AddOrUpdateDeckLegacyRequest) returns (DeckId);
rpc DeckTree(DeckTreeRequest) returns (DeckTreeNode); rpc DeckTree(DeckTreeRequest) returns (DeckTreeNode);
rpc DeckTreeLegacy(generic.Empty) returns (generic.Json); rpc DeckTreeLegacy(generic.Empty) returns (generic.Json);
rpc GetAllDecksLegacy(generic.Empty) returns (generic.Json); rpc GetAllDecksLegacy(generic.Empty) returns (generic.Json);
rpc GetDeckIdByName(generic.String) returns (DeckId); rpc GetDeckIdByName(generic.String) returns (DeckId);
rpc GetDeck(DeckId) returns (Deck); rpc GetDeck(DeckId) returns (Deck);
rpc UpdateDeck(Deck) returns (OpChanges); rpc UpdateDeck(Deck) returns (collection.OpChanges);
rpc UpdateDeckLegacy(generic.Json) returns (OpChanges); rpc UpdateDeckLegacy(generic.Json) returns (collection.OpChanges);
rpc SetDeckCollapsed(SetDeckCollapsedRequest) returns (OpChanges); rpc SetDeckCollapsed(SetDeckCollapsedRequest) returns (collection.OpChanges);
rpc GetDeckLegacy(DeckId) returns (generic.Json); rpc GetDeckLegacy(DeckId) returns (generic.Json);
rpc GetDeckNames(GetDeckNamesRequest) returns (DeckNames); rpc GetDeckNames(GetDeckNamesRequest) returns (DeckNames);
rpc NewDeckLegacy(generic.Bool) returns (generic.Json); rpc NewDeckLegacy(generic.Bool) returns (generic.Json);
rpc RemoveDecks(DeckIds) returns (OpChangesWithCount); rpc RemoveDecks(DeckIds) returns (collection.OpChangesWithCount);
rpc ReparentDecks(ReparentDecksRequest) returns (OpChangesWithCount); rpc ReparentDecks(ReparentDecksRequest)
rpc RenameDeck(RenameDeckRequest) returns (OpChanges); returns (collection.OpChangesWithCount);
rpc RenameDeck(RenameDeckRequest) returns (collection.OpChanges);
rpc GetOrCreateFilteredDeck(DeckId) returns (FilteredDeckForUpdate); rpc GetOrCreateFilteredDeck(DeckId) returns (FilteredDeckForUpdate);
rpc AddOrUpdateFilteredDeck(FilteredDeckForUpdate) returns (OpChangesWithId); rpc AddOrUpdateFilteredDeck(FilteredDeckForUpdate)
returns (collection.OpChangesWithId);
rpc FilteredDeckOrderLabels(generic.Empty) returns (generic.StringList); rpc FilteredDeckOrderLabels(generic.Empty) returns (generic.StringList);
rpc SetCurrentDeck(DeckId) returns (OpChanges); rpc SetCurrentDeck(DeckId) returns (collection.OpChanges);
rpc GetCurrentDeck(generic.Empty) returns (Deck); rpc GetCurrentDeck(generic.Empty) returns (Deck);
} }
@ -121,15 +119,16 @@ service NotesService {
rpc AddNote(AddNoteRequest) returns (AddNoteResponse); rpc AddNote(AddNoteRequest) returns (AddNoteResponse);
rpc DefaultsForAdding(DefaultsForAddingRequest) returns (DeckAndNotetype); rpc DefaultsForAdding(DefaultsForAddingRequest) returns (DeckAndNotetype);
rpc DefaultDeckForNotetype(NotetypeId) returns (DeckId); rpc DefaultDeckForNotetype(NotetypeId) returns (DeckId);
rpc UpdateNote(UpdateNoteRequest) returns (OpChanges); rpc UpdateNote(UpdateNoteRequest) returns (collection.OpChanges);
rpc GetNote(NoteId) returns (Note); rpc GetNote(NoteId) returns (Note);
rpc RemoveNotes(RemoveNotesRequest) returns (OpChangesWithCount); rpc RemoveNotes(RemoveNotesRequest) returns (collection.OpChangesWithCount);
rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteResponse); rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteResponse);
rpc AfterNoteUpdates(AfterNoteUpdatesRequest) returns (OpChangesWithCount); rpc AfterNoteUpdates(AfterNoteUpdatesRequest)
returns (collection.OpChangesWithCount);
rpc FieldNamesForNotes(FieldNamesForNotesRequest) rpc FieldNamesForNotes(FieldNamesForNotesRequest)
returns (FieldNamesForNotesResponse); returns (FieldNamesForNotesResponse);
rpc NoteFieldsCheck(Note) returns (NoteFieldsCheckResponse); rpc NoteFieldsCheck(Note) returns (NoteFieldsCheckResponse);
rpc CardsOfNote(NoteId) returns (CardIds); rpc CardsOfNote(NoteId) returns (cards.CardIds);
} }
service SyncService { service SyncService {
@ -147,23 +146,23 @@ service SyncService {
service ConfigService { service ConfigService {
rpc GetConfigJson(generic.String) returns (generic.Json); rpc GetConfigJson(generic.String) returns (generic.Json);
rpc SetConfigJson(SetConfigJsonRequest) returns (OpChanges); rpc SetConfigJson(SetConfigJsonRequest) returns (collection.OpChanges);
rpc SetConfigJsonNoUndo(SetConfigJsonRequest) returns (generic.Empty); rpc SetConfigJsonNoUndo(SetConfigJsonRequest) returns (generic.Empty);
rpc RemoveConfig(generic.String) returns (OpChanges); rpc RemoveConfig(generic.String) returns (collection.OpChanges);
rpc GetAllConfig(generic.Empty) returns (generic.Json); rpc GetAllConfig(generic.Empty) returns (generic.Json);
rpc GetConfigBool(Config.Bool) returns (generic.Bool); rpc GetConfigBool(Config.Bool) returns (generic.Bool);
rpc SetConfigBool(SetConfigBoolRequest) returns (OpChanges); rpc SetConfigBool(SetConfigBoolRequest) returns (collection.OpChanges);
rpc GetConfigString(Config.String) returns (generic.String); rpc GetConfigString(Config.String) returns (generic.String);
rpc SetConfigString(SetConfigStringRequest) returns (OpChanges); rpc SetConfigString(SetConfigStringRequest) returns (collection.OpChanges);
rpc GetPreferences(generic.Empty) returns (Preferences); rpc GetPreferences(generic.Empty) returns (Preferences);
rpc SetPreferences(Preferences) returns (OpChanges); rpc SetPreferences(Preferences) returns (collection.OpChanges);
} }
service NotetypesService { service NotetypesService {
rpc AddNotetype(Notetype) returns (OpChangesWithId); rpc AddNotetype(Notetype) returns (collection.OpChangesWithId);
rpc UpdateNotetype(Notetype) returns (OpChanges); rpc UpdateNotetype(Notetype) returns (collection.OpChanges);
rpc AddNotetypeLegacy(generic.Json) returns (OpChangesWithId); rpc AddNotetypeLegacy(generic.Json) returns (collection.OpChangesWithId);
rpc UpdateNotetypeLegacy(generic.Json) returns (OpChanges); rpc UpdateNotetypeLegacy(generic.Json) returns (collection.OpChanges);
rpc AddOrUpdateNotetype(AddOrUpdateNotetypeRequest) returns (NotetypeId); rpc AddOrUpdateNotetype(AddOrUpdateNotetypeRequest) returns (NotetypeId);
rpc GetStockNotetypeLegacy(StockNotetype) returns (generic.Json); rpc GetStockNotetypeLegacy(StockNotetype) returns (generic.Json);
rpc GetNotetype(NotetypeId) returns (Notetype); rpc GetNotetype(NotetypeId) returns (Notetype);
@ -171,14 +170,14 @@ service NotetypesService {
rpc GetNotetypeNames(generic.Empty) returns (NotetypeNames); rpc GetNotetypeNames(generic.Empty) returns (NotetypeNames);
rpc GetNotetypeNamesAndCounts(generic.Empty) returns (NotetypeUseCounts); rpc GetNotetypeNamesAndCounts(generic.Empty) returns (NotetypeUseCounts);
rpc GetNotetypeIdByName(generic.String) returns (NotetypeId); rpc GetNotetypeIdByName(generic.String) returns (NotetypeId);
rpc RemoveNotetype(NotetypeId) returns (OpChanges); rpc RemoveNotetype(NotetypeId) returns (collection.OpChanges);
rpc GetAuxNotetypeConfigKey(GetAuxConfigKeyRequest) returns (generic.String); rpc GetAuxNotetypeConfigKey(GetAuxConfigKeyRequest) returns (generic.String);
rpc GetAuxTemplateConfigKey(GetAuxTemplateConfigKeyRequest) rpc GetAuxTemplateConfigKey(GetAuxTemplateConfigKeyRequest)
returns (generic.String); returns (generic.String);
rpc GetSingleNotetypeOfNotes(NoteIds) returns (NotetypeId); rpc GetSingleNotetypeOfNotes(NoteIds) returns (NotetypeId);
rpc GetChangeNotetypeInfo(GetChangeNotetypeInfoRequest) rpc GetChangeNotetypeInfo(GetChangeNotetypeInfoRequest)
returns (ChangeNotetypeInfo); returns (ChangeNotetypeInfo);
rpc ChangeNotetype(ChangeNotetypeRequest) returns (OpChanges); rpc ChangeNotetype(ChangeNotetypeRequest) returns (collection.OpChanges);
} }
service CardRenderingService { service CardRenderingService {
@ -203,20 +202,24 @@ service DeckConfigService {
rpc NewDeckConfigLegacy(generic.Empty) returns (generic.Json); rpc NewDeckConfigLegacy(generic.Empty) returns (generic.Json);
rpc RemoveDeckConfig(DeckConfigId) returns (generic.Empty); rpc RemoveDeckConfig(DeckConfigId) returns (generic.Empty);
rpc GetDeckConfigsForUpdate(DeckId) returns (DeckConfigsForUpdate); rpc GetDeckConfigsForUpdate(DeckId) returns (DeckConfigsForUpdate);
rpc UpdateDeckConfigs(UpdateDeckConfigsRequest) returns (OpChanges); rpc UpdateDeckConfigs(UpdateDeckConfigsRequest)
returns (collection.OpChanges);
} }
service TagsService { service TagsService {
rpc ClearUnusedTags(generic.Empty) returns (OpChangesWithCount); rpc ClearUnusedTags(generic.Empty) returns (collection.OpChangesWithCount);
rpc AllTags(generic.Empty) returns (generic.StringList); rpc AllTags(generic.Empty) returns (generic.StringList);
rpc RemoveTags(generic.String) returns (OpChangesWithCount); rpc RemoveTags(generic.String) returns (collection.OpChangesWithCount);
rpc SetTagCollapsed(SetTagCollapsedRequest) returns (OpChanges); rpc SetTagCollapsed(SetTagCollapsedRequest) returns (collection.OpChanges);
rpc TagTree(generic.Empty) returns (TagTreeNode); rpc TagTree(generic.Empty) returns (TagTreeNode);
rpc ReparentTags(ReparentTagsRequest) returns (OpChangesWithCount); rpc ReparentTags(ReparentTagsRequest) returns (collection.OpChangesWithCount);
rpc RenameTags(RenameTagsRequest) returns (OpChangesWithCount); rpc RenameTags(RenameTagsRequest) returns (collection.OpChangesWithCount);
rpc AddNoteTags(NoteIdsAndTagsRequest) returns (OpChangesWithCount); rpc AddNoteTags(NoteIdsAndTagsRequest)
rpc RemoveNoteTags(NoteIdsAndTagsRequest) returns (OpChangesWithCount); returns (collection.OpChangesWithCount);
rpc FindAndReplaceTag(FindAndReplaceTagRequest) returns (OpChangesWithCount); rpc RemoveNoteTags(NoteIdsAndTagsRequest)
returns (collection.OpChangesWithCount);
rpc FindAndReplaceTag(FindAndReplaceTagRequest)
returns (collection.OpChangesWithCount);
} }
service SearchService { service SearchService {
@ -225,14 +228,15 @@ service SearchService {
rpc SearchNotes(SearchRequest) returns (SearchResponse); rpc SearchNotes(SearchRequest) returns (SearchResponse);
rpc JoinSearchNodes(JoinSearchNodesRequest) returns (generic.String); rpc JoinSearchNodes(JoinSearchNodesRequest) returns (generic.String);
rpc ReplaceSearchNode(ReplaceSearchNodeRequest) returns (generic.String); rpc ReplaceSearchNode(ReplaceSearchNodeRequest) returns (generic.String);
rpc FindAndReplace(FindAndReplaceRequest) returns (OpChangesWithCount); rpc FindAndReplace(FindAndReplaceRequest)
returns (collection.OpChangesWithCount);
rpc AllBrowserColumns(generic.Empty) returns (BrowserColumns); rpc AllBrowserColumns(generic.Empty) returns (BrowserColumns);
rpc BrowserRowForId(generic.Int64) returns (BrowserRow); rpc BrowserRowForId(generic.Int64) returns (BrowserRow);
rpc SetActiveBrowserColumns(generic.StringList) returns (generic.Empty); rpc SetActiveBrowserColumns(generic.StringList) returns (generic.Empty);
} }
service StatsService { service StatsService {
rpc CardStats(CardId) returns (generic.String); rpc CardStats(cards.CardId) returns (generic.String);
rpc Graphs(GraphsRequest) returns (GraphsResponse); rpc Graphs(GraphsRequest) returns (GraphsResponse);
rpc GetGraphPreferences(generic.Empty) returns (GraphPreferences); rpc GetGraphPreferences(generic.Empty) returns (GraphPreferences);
rpc SetGraphPreferences(GraphPreferences) returns (generic.Empty); rpc SetGraphPreferences(GraphPreferences) returns (generic.Empty);
@ -246,27 +250,6 @@ service MediaService {
rpc RestoreTrash(generic.Empty) returns (generic.Empty); rpc RestoreTrash(generic.Empty) returns (generic.Empty);
} }
service CollectionService {
rpc OpenCollection(OpenCollectionRequest) returns (generic.Empty);
rpc CloseCollection(CloseCollectionRequest) returns (generic.Empty);
rpc CheckDatabase(generic.Empty) returns (CheckDatabaseResponse);
rpc GetUndoStatus(generic.Empty) returns (UndoStatus);
rpc Undo(generic.Empty) returns (OpChangesAfterUndo);
rpc Redo(generic.Empty) returns (OpChangesAfterUndo);
rpc AddCustomUndoEntry(generic.String) returns (generic.UInt32);
rpc MergeUndoEntries(generic.UInt32) returns (OpChanges);
rpc LatestProgress(generic.Empty) returns (Progress);
rpc SetWantsAbort(generic.Empty) returns (generic.Empty);
}
service CardsService {
rpc GetCard(CardId) returns (Card);
rpc UpdateCard(UpdateCardRequest) returns (OpChanges);
rpc RemoveCards(RemoveCardsRequest) returns (generic.Empty);
rpc SetDeck(SetDeckRequest) returns (OpChangesWithCount);
rpc SetFlag(SetFlagRequest) returns (OpChangesWithCount);
}
// Protobuf stored in .anki2 files // Protobuf stored in .anki2 files
// These should be moved to a separate file in the future // These should be moved to a separate file in the future
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -518,27 +501,6 @@ message Note {
repeated string fields = 7; repeated string fields = 7;
} }
message Card {
int64 id = 1;
int64 note_id = 2;
int64 deck_id = 3;
uint32 template_idx = 4;
int64 mtime_secs = 5;
sint32 usn = 6;
uint32 ctype = 7;
sint32 queue = 8;
sint32 due = 9;
uint32 interval = 10;
uint32 ease_factor = 11;
uint32 reps = 12;
uint32 lapses = 13;
uint32 remaining_steps = 14;
sint32 original_due = 15;
int64 original_deck_id = 16;
uint32 flags = 17;
string data = 18;
}
// Backend // Backend
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -581,42 +543,6 @@ message BackendError {
Kind kind = 2; Kind kind = 2;
} }
// Progress
///////////////////////////////////////////////////////////
message Progress {
message MediaSync {
string checked = 1;
string added = 2;
string removed = 3;
}
message FullSync {
uint32 transferred = 1;
uint32 total = 2;
}
message NormalSync {
string stage = 1;
string added = 2;
string removed = 3;
}
message DatabaseCheck {
string stage = 1;
uint32 stage_total = 2;
uint32 stage_current = 3;
}
oneof value {
generic.Empty none = 1;
MediaSync media_sync = 2;
string media_check = 3;
FullSync full_sync = 4;
NormalSync normal_sync = 5;
DatabaseCheck database_check = 6;
}
}
// Messages // Messages
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -754,13 +680,6 @@ message CongratsLearnMessageRequest {
uint32 remaining = 2; uint32 remaining = 2;
} }
message OpenCollectionRequest {
string collection_path = 1;
string media_folder_path = 2;
string media_db_path = 3;
string log_path = 4;
}
message SearchRequest { message SearchRequest {
string search = 1; string search = 1;
SortOrder order = 2; SortOrder order = 2;
@ -863,10 +782,6 @@ message ReplaceSearchNodeRequest {
SearchNode replacement_node = 2; SearchNode replacement_node = 2;
} }
message CloseCollectionRequest {
bool downgrade_to_schema11 = 1;
}
message DeckConfigsForUpdate { message DeckConfigsForUpdate {
message ConfigWithExtra { message ConfigWithExtra {
DeckConfig config = 1; DeckConfig config = 1;
@ -984,7 +899,7 @@ message AddNoteRequest {
message AddNoteResponse { message AddNoteResponse {
int64 note_id = 1; int64 note_id = 1;
OpChanges changes = 2; collection.OpChanges changes = 2;
} }
message UpdateNoteRequest { message UpdateNoteRequest {
@ -992,11 +907,6 @@ message UpdateNoteRequest {
bool skip_undo_entry = 2; bool skip_undo_entry = 2;
} }
message UpdateCardRequest {
Card card = 1;
bool skip_undo_entry = 2;
}
message EmptyCardsReport { message EmptyCardsReport {
message NoteWithEmptyCards { message NoteWithEmptyCards {
int64 note_id = 1; int64 note_id = 1;
@ -1101,10 +1011,6 @@ message FindAndReplaceTagRequest {
bool match_case = 5; bool match_case = 5;
} }
message CheckDatabaseResponse {
repeated string problems = 1;
}
message Preferences { message Preferences {
message Scheduling { message Scheduling {
enum NewReviewMix { enum NewReviewMix {
@ -1230,10 +1136,6 @@ message RemoveNotesRequest {
repeated int64 card_ids = 2; repeated int64 card_ids = 2;
} }
message RemoveCardsRequest {
repeated int64 card_ids = 1;
}
message UpdateStatsRequest { message UpdateStatsRequest {
int64 deck_id = 1; int64 deck_id = 1;
int32 new_delta = 2; int32 new_delta = 2;
@ -1258,7 +1160,7 @@ message GraphsRequest {
} }
message GraphsResponse { message GraphsResponse {
repeated Card cards = 1; repeated cards.Card cards = 1;
repeated RevlogEntry revlog = 2; repeated RevlogEntry revlog = 2;
uint32 days_elapsed = 3; uint32 days_elapsed = 3;
// Based on rollover hour // Based on rollover hour
@ -1357,11 +1259,6 @@ message SortDeckRequest {
bool randomize = 2; bool randomize = 2;
} }
message SetDeckRequest {
repeated int64 card_ids = 1;
int64 deck_id = 2;
}
message Config { message Config {
message Bool { message Bool {
enum Key { enum Key {
@ -1496,7 +1393,7 @@ message QueuedCards {
REVIEW = 2; REVIEW = 2;
} }
message QueuedCard { message QueuedCard {
Card card = 1; cards.Card card = 1;
Queue queue = 2; Queue queue = 2;
NextCardStates next_states = 3; NextCardStates next_states = 3;
} }
@ -1507,48 +1404,6 @@ message QueuedCards {
uint32 review_count = 4; uint32 review_count = 4;
} }
message OpChanges {
bool card = 1;
bool note = 2;
bool deck = 3;
bool tag = 4;
bool notetype = 5;
bool config = 6;
bool deck_config = 11;
bool mtime = 12;
bool browser_table = 7;
bool browser_sidebar = 8;
// editor and displayed card in review screen
bool note_text = 9;
// whether to call .reset() and getCard()
bool study_queues = 10;
}
message OpChangesWithCount {
uint32 count = 1;
OpChanges changes = 2;
}
message OpChangesWithId {
int64 id = 1;
OpChanges changes = 2;
}
message UndoStatus {
string undo = 1;
string redo = 2;
uint32 last_step = 3;
}
message OpChangesAfterUndo {
OpChanges changes = 1;
string operation = 2;
int64 reverted_to_timestamp = 3;
UndoStatus new_status = 4;
uint32 counter = 5;
}
message DefaultsForAddingRequest { message DefaultsForAddingRequest {
int64 home_deck_of_current_review_card = 1; int64 home_deck_of_current_review_card = 1;
} }
@ -1569,11 +1424,6 @@ message FilteredDeckForUpdate {
Deck.Filtered config = 3; Deck.Filtered config = 3;
} }
message SetFlagRequest {
repeated int64 card_ids = 1;
uint32 flag = 2;
}
message GetAuxConfigKeyRequest { message GetAuxConfigKeyRequest {
int64 id = 1; int64 id = 1;
string key = 2; string key = 2;

64
proto/anki/cards.proto Normal file
View file

@ -0,0 +1,64 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
syntax = "proto3";
package anki.cards;
import "anki/generic.proto";
import "anki/collection.proto";
service CardsService {
rpc GetCard(CardId) returns (Card);
rpc UpdateCard(UpdateCardRequest) returns (collection.OpChanges);
rpc RemoveCards(RemoveCardsRequest) returns (generic.Empty);
rpc SetDeck(SetDeckRequest) returns (collection.OpChangesWithCount);
rpc SetFlag(SetFlagRequest) returns (collection.OpChangesWithCount);
}
message CardId {
int64 cid = 1;
}
message CardIds {
repeated int64 cids = 1;
}
message Card {
int64 id = 1;
int64 note_id = 2;
int64 deck_id = 3;
uint32 template_idx = 4;
int64 mtime_secs = 5;
sint32 usn = 6;
uint32 ctype = 7;
sint32 queue = 8;
sint32 due = 9;
uint32 interval = 10;
uint32 ease_factor = 11;
uint32 reps = 12;
uint32 lapses = 13;
uint32 remaining_steps = 14;
sint32 original_due = 15;
int64 original_deck_id = 16;
uint32 flags = 17;
string data = 18;
}
message UpdateCardRequest {
Card card = 1;
bool skip_undo_entry = 2;
}
message RemoveCardsRequest {
repeated int64 card_ids = 1;
}
message SetDeckRequest {
repeated int64 card_ids = 1;
int64 deck_id = 2;
}
message SetFlagRequest {
repeated int64 card_ids = 1;
uint32 flag = 2;
}

111
proto/anki/collection.proto Normal file
View file

@ -0,0 +1,111 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
syntax = "proto3";
package anki.collection;
import "anki/generic.proto";
service CollectionService {
rpc OpenCollection(OpenCollectionRequest) returns (generic.Empty);
rpc CloseCollection(CloseCollectionRequest) returns (generic.Empty);
rpc CheckDatabase(generic.Empty) returns (CheckDatabaseResponse);
rpc GetUndoStatus(generic.Empty) returns (UndoStatus);
rpc Undo(generic.Empty) returns (OpChangesAfterUndo);
rpc Redo(generic.Empty) returns (OpChangesAfterUndo);
rpc AddCustomUndoEntry(generic.String) returns (generic.UInt32);
rpc MergeUndoEntries(generic.UInt32) returns (OpChanges);
rpc LatestProgress(generic.Empty) returns (Progress);
rpc SetWantsAbort(generic.Empty) returns (generic.Empty);
}
message OpenCollectionRequest {
string collection_path = 1;
string media_folder_path = 2;
string media_db_path = 3;
string log_path = 4;
}
message CloseCollectionRequest {
bool downgrade_to_schema11 = 1;
}
message CheckDatabaseResponse {
repeated string problems = 1;
}
message OpChanges {
bool card = 1;
bool note = 2;
bool deck = 3;
bool tag = 4;
bool notetype = 5;
bool config = 6;
bool deck_config = 11;
bool mtime = 12;
bool browser_table = 7;
bool browser_sidebar = 8;
// editor and displayed card in review screen
bool note_text = 9;
// whether to call .reset() and getCard()
bool study_queues = 10;
}
message OpChangesWithCount {
uint32 count = 1;
OpChanges changes = 2;
}
message OpChangesWithId {
int64 id = 1;
OpChanges changes = 2;
}
message UndoStatus {
string undo = 1;
string redo = 2;
uint32 last_step = 3;
}
message OpChangesAfterUndo {
OpChanges changes = 1;
string operation = 2;
int64 reverted_to_timestamp = 3;
UndoStatus new_status = 4;
uint32 counter = 5;
}
message Progress {
message MediaSync {
string checked = 1;
string added = 2;
string removed = 3;
}
message FullSync {
uint32 transferred = 1;
uint32 total = 2;
}
message NormalSync {
string stage = 1;
string added = 2;
string removed = 3;
}
message DatabaseCheck {
string stage = 1;
uint32 stage_total = 2;
uint32 stage_current = 3;
}
oneof value {
generic.Empty none = 1;
MediaSync media_sync = 2;
string media_check = 3;
FullSync full_sync = 4;
NormalSync normal_sync = 5;
DatabaseCheck database_check = 6;
}
}

View file

@ -10,6 +10,8 @@ import google.protobuf.descriptor
import anki.backend_pb2 import anki.backend_pb2
import anki.i18n_pb2 import anki.i18n_pb2
import anki.cards_pb2
import anki.collection_pb2
import stringcase import stringcase
@ -165,14 +167,18 @@ def render_service(
out.append(render_method(service_index, method_index, method)) out.append(render_method(service_index, method_index, method))
service_modules = dict(I18N="i18n") service_modules = dict(
I18N=anki.i18n_pb2,
COLLECTION=anki.collection_pb2,
CARDS=anki.cards_pb2,
)
for service in anki.backend_pb2.ServiceIndex.DESCRIPTOR.values: for service in anki.backend_pb2.ServiceIndex.DESCRIPTOR.values:
# SERVICE_INDEX_TEST -> _TESTSERVICE # SERVICE_INDEX_TEST -> _TESTSERVICE
base = service.name.replace("SERVICE_INDEX_", "") base = service.name.replace("SERVICE_INDEX_", "")
service_pkg = (service_modules.get(base) or "backend") + "" service_pkg = service_modules.get(base) or anki.backend_pb2
service_var = "_" + base.replace("_", "") + "SERVICE" service_var = "_" + base.replace("_", "") + "SERVICE"
service_obj = getattr(getattr(anki, service_pkg + "_pb2"), service_var) service_obj = getattr(service_pkg, service_var)
service_index = service.number service_index = service.number
render_service(service_obj, service_index) render_service(service_obj, service_index)

View file

@ -10,8 +10,7 @@ import time
from typing import List, NewType, Optional from typing import List, NewType, Optional
import anki # pylint: disable=unused-import import anki # pylint: disable=unused-import
import anki.backend_pb2 as _pb from anki import cards_pb2, hooks
from anki import hooks
from anki._legacy import DeprecatedNamesMixin, deprecated from anki._legacy import DeprecatedNamesMixin, deprecated
from anki.consts import * from anki.consts import *
from anki.models import NotetypeDict, TemplateDict from anki.models import NotetypeDict, TemplateDict
@ -31,7 +30,7 @@ from anki.sound import AVTag
# types # types
CardId = NewType("CardId", int) CardId = NewType("CardId", int)
BackendCard = _pb.Card BackendCard = cards_pb2.Card
class Card(DeprecatedNamesMixin): class Card(DeprecatedNamesMixin):
@ -62,14 +61,14 @@ class Card(DeprecatedNamesMixin):
self._load_from_backend_card(backend_card) self._load_from_backend_card(backend_card)
else: else:
# new card with defaults # new card with defaults
self._load_from_backend_card(_pb.Card()) self._load_from_backend_card(cards_pb2.Card())
def load(self) -> None: def load(self) -> None:
card = self.col._backend.get_card(self.id) card = self.col._backend.get_card(self.id)
assert card assert card
self._load_from_backend_card(card) self._load_from_backend_card(card)
def _load_from_backend_card(self, card: _pb.Card) -> None: def _load_from_backend_card(self, card: cards_pb2.Card) -> None:
self._render_output = None self._render_output = None
self._note = None self._note = None
self.id = CardId(card.id) self.id = CardId(card.id)
@ -91,9 +90,9 @@ class Card(DeprecatedNamesMixin):
self.flags = card.flags self.flags = card.flags
self.data = card.data self.data = card.data
def _to_backend_card(self) -> _pb.Card: def _to_backend_card(self) -> cards_pb2.Card:
# mtime & usn are set by backend # mtime & usn are set by backend
return _pb.Card( return cards_pb2.Card(
id=self.id, id=self.id,
note_id=self.nid, note_id=self.nid,
deck_id=self.did, deck_id=self.did,

1
pylib/anki/cards_pb2.pyi Symbolic link
View file

@ -0,0 +1 @@
../../bazel-bin/pylib/anki/cards_pb2.pyi

View file

@ -8,20 +8,20 @@ from __future__ import annotations
from typing import Any, Generator, List, Literal, Optional, Sequence, Tuple, Union, cast from typing import Any, Generator, List, Literal, Optional, Sequence, Tuple, Union, cast
import anki.backend_pb2 as _pb import anki.backend_pb2 as _pb
from anki import collection_pb2
# protobuf we publicly export - listed first to avoid circular imports
from anki._legacy import DeprecatedNamesMixin, deprecated from anki._legacy import DeprecatedNamesMixin, deprecated
# protobuf we publicly export - listed first to avoid circular imports
SearchNode = _pb.SearchNode SearchNode = _pb.SearchNode
Progress = _pb.Progress Progress = collection_pb2.Progress
EmptyCardsReport = _pb.EmptyCardsReport EmptyCardsReport = _pb.EmptyCardsReport
GraphPreferences = _pb.GraphPreferences GraphPreferences = _pb.GraphPreferences
Preferences = _pb.Preferences Preferences = _pb.Preferences
UndoStatus = _pb.UndoStatus UndoStatus = collection_pb2.UndoStatus
OpChanges = _pb.OpChanges OpChanges = collection_pb2.OpChanges
OpChangesWithCount = _pb.OpChangesWithCount OpChangesWithCount = collection_pb2.OpChangesWithCount
OpChangesWithId = _pb.OpChangesWithId OpChangesWithId = collection_pb2.OpChangesWithId
OpChangesAfterUndo = _pb.OpChangesAfterUndo OpChangesAfterUndo = collection_pb2.OpChangesAfterUndo
DefaultsForAdding = _pb.DeckAndNotetype DefaultsForAdding = _pb.DeckAndNotetype
BrowserRow = _pb.BrowserRow BrowserRow = _pb.BrowserRow
BrowserColumns = _pb.BrowserColumns BrowserColumns = _pb.BrowserColumns

View file

@ -0,0 +1 @@
../../bazel-bin/pylib/anki/collection_pb2.pyi

View file

@ -10,7 +10,15 @@ pub mod i18n {
pub mod generic { pub mod generic {
include!(concat!(env!("OUT_DIR"), "/anki.generic.rs")); include!(concat!(env!("OUT_DIR"), "/anki.generic.rs"));
} }
pub mod cards {
include!(concat!(env!("OUT_DIR"), "/anki.cards.rs"));
}
pub mod collection {
include!(concat!(env!("OUT_DIR"), "/anki.collection.rs"));
}
pub use backend::*; pub use backend::*;
pub use cards::*;
pub use collection::*;
pub use generic::*; pub use generic::*;
pub use i18n::*; pub use i18n::*;

View file

@ -6,7 +6,7 @@
@typescript-eslint/no-explicit-any: "off", @typescript-eslint/no-explicit-any: "off",
*/ */
import type { Backend } from "lib/proto"; import type { Backend, Cards } from "lib/proto";
import { import {
extent, extent,
@ -29,7 +29,7 @@ export interface GraphData {
} }
export function gatherData(data: Backend.GraphsResponse): GraphData { export function gatherData(data: Backend.GraphsResponse): GraphData {
const daysAdded = (data.cards as Backend.Card[]).map((card) => { const daysAdded = (data.cards as Cards.Card[]).map((card) => {
const elapsedSecs = (card.id as number) / 1000 - data.nextDayAtSecs; const elapsedSecs = (card.id as number) / 1000 - data.nextDayAtSecs;
return Math.ceil(elapsedSecs / 86400); return Math.ceil(elapsedSecs / 86400);
}); });

View file

@ -7,7 +7,7 @@
*/ */
import { CardQueue, CardType } from "lib/cards"; import { CardQueue, CardType } from "lib/cards";
import type { Backend } from "lib/proto"; import type { Backend, Cards } from "lib/proto";
import { import {
schemeGreens, schemeGreens,
schemeBlues, schemeBlues,
@ -41,7 +41,7 @@ const barColours = [
"grey" /* buried */, "grey" /* buried */,
]; ];
function countCards(cards: Backend.ICard[], separateInactive: boolean): Count[] { function countCards(cards: Cards.ICard[], separateInactive: boolean): Count[] {
let newCards = 0; let newCards = 0;
let learn = 0; let learn = 0;
let relearn = 0; let relearn = 0;
@ -50,7 +50,7 @@ function countCards(cards: Backend.ICard[], separateInactive: boolean): Count[]
let suspended = 0; let suspended = 0;
let buried = 0; let buried = 0;
for (const card of cards as Backend.Card[]) { for (const card of cards as Cards.Card[]) {
if (separateInactive) { if (separateInactive) {
switch (card.queue) { switch (card.queue) {
case CardQueue.Suspended: case CardQueue.Suspended:

View file

@ -6,7 +6,7 @@
@typescript-eslint/no-explicit-any: "off", @typescript-eslint/no-explicit-any: "off",
*/ */
import type { Backend } from "lib/proto"; import type { Backend, Cards } from "lib/proto";
import { import {
extent, extent,
histogram, histogram,
@ -27,7 +27,7 @@ export interface GraphData {
} }
export function gatherData(data: Backend.GraphsResponse): GraphData { export function gatherData(data: Backend.GraphsResponse): GraphData {
const eases = (data.cards as Backend.Card[]) const eases = (data.cards as Cards.Card[])
.filter((c) => [CardType.Review, CardType.Relearn].includes(c.ctype)) .filter((c) => [CardType.Review, CardType.Relearn].includes(c.ctype))
.map((c) => c.easeFactor / 10); .map((c) => c.easeFactor / 10);
return { eases }; return { eases };

View file

@ -6,7 +6,7 @@
@typescript-eslint/no-explicit-any: "off", @typescript-eslint/no-explicit-any: "off",
*/ */
import type { Backend } from "lib/proto"; import type { Backend, Cards } from "lib/proto";
import { import {
extent, extent,
histogram, histogram,
@ -31,12 +31,12 @@ export interface GraphData {
} }
export function gatherData(data: Backend.GraphsResponse): GraphData { export function gatherData(data: Backend.GraphsResponse): GraphData {
const isLearning = (card: Backend.Card): boolean => const isLearning = (card: Cards.Card): boolean =>
[CardQueue.Learn, CardQueue.PreviewRepeat].includes(card.queue); [CardQueue.Learn, CardQueue.PreviewRepeat].includes(card.queue);
let haveBacklog = false; let haveBacklog = false;
const due = (data.cards as Backend.Card[]) const due = (data.cards as Cards.Card[])
.filter((c: Backend.Card) => { .filter((c: Cards.Card) => {
// reviews // reviews
return ( return (
[CardQueue.Review, CardQueue.DayLearn].includes(c.queue) || [CardQueue.Review, CardQueue.DayLearn].includes(c.queue) ||
@ -44,7 +44,7 @@ export function gatherData(data: Backend.GraphsResponse): GraphData {
isLearning(c) isLearning(c)
); );
}) })
.map((c: Backend.Card) => { .map((c: Cards.Card) => {
let dueDay: number; let dueDay: number;
if (isLearning(c)) { if (isLearning(c)) {

View file

@ -6,7 +6,7 @@
@typescript-eslint/no-explicit-any: "off", @typescript-eslint/no-explicit-any: "off",
@typescript-eslint/ban-ts-comment: "off" */ @typescript-eslint/ban-ts-comment: "off" */
import type { Backend } from "lib/proto"; import type { Backend, Cards } from "lib/proto";
import type { Selection } from "d3"; import type { Selection } from "d3";
// amount of data to fetch from backend // amount of data to fetch from backend
@ -28,7 +28,7 @@ export enum GraphRange {
} }
export interface GraphsContext { export interface GraphsContext {
cards: Backend.Card[]; cards: Cards.Card[];
revlog: Backend.RevlogEntry[]; revlog: Backend.RevlogEntry[];
revlogRange: RevlogRange; revlogRange: RevlogRange;
nightMode: boolean; nightMode: boolean;

View file

@ -6,7 +6,7 @@
@typescript-eslint/no-explicit-any: "off", @typescript-eslint/no-explicit-any: "off",
*/ */
import type { Backend } from "lib/proto"; import type { Backend, Cards } from "lib/proto";
import { import {
extent, extent,
histogram, histogram,
@ -37,7 +37,7 @@ export enum IntervalRange {
} }
export function gatherIntervalData(data: Backend.GraphsResponse): IntervalGraphData { export function gatherIntervalData(data: Backend.GraphsResponse): IntervalGraphData {
const intervals = (data.cards as Backend.Card[]) const intervals = (data.cards as Cards.Card[])
.filter((c) => [CardType.Review, CardType.Relearn].includes(c.ctype)) .filter((c) => [CardType.Review, CardType.Relearn].includes(c.ctype))
.map((c) => c.interval); .map((c) => c.interval);
return { intervals }; return { intervals };

View file

@ -3,4 +3,5 @@
import { anki } from "./backend_proto"; import { anki } from "./backend_proto";
import Backend = anki.backend; import Backend = anki.backend;
export { Backend }; import Cards = anki.cards;
export { Backend, Cards };