refactor protobuf handling for split/import
In order to split backend.proto into a more manageable size, the protobuf handling needed to be updated. This took more time than I would have liked, as each language handles protobuf differently: - The Python Protobuf code ignores "package" directives, and relies solely on how the files are laid out on disk. While it would have been nice to keep the generated files in a private subpackage, Protobuf gets confused if the files are located in a location that does not match their original .proto layout, so the old approach of storing them in _backend/ will not work. They now clutter up pylib/anki instead. I'm rather annoyed by that, but alternatives seem to be having to add an extra level to the Protobuf path, making the other languages suffer, or trying to hack around the issue by munging sys.modules. - Protobufjs fails to expose packages if they don't start with a capital letter, despite the fact that lowercase packages are the norm in most languages :-( This required a patch to fix. - Rust was the easiest, as Prost is relatively straightforward compared to Google's tools. The Protobuf files are now stored in /proto/anki, with a separate package for each file. I've split backend.proto into a few files as a test, but the majority of that work is still to come. The Python Protobuf building is a bit of a hack at the moment, hard-coding "proto" as the top level folder, but it seems to get the job done for now. Also changed the workspace name, as there seems to be a number of Bazel repos moving away from the more awkward reverse DNS naming style.
This commit is contained in:
parent
1d4b58419e
commit
616db33c0e
@ -1,5 +1,5 @@
|
||||
workspace(
|
||||
name = "net_ankiweb_anki",
|
||||
name = "anki",
|
||||
managed_directories = {"@npm": [
|
||||
"ts/node_modules",
|
||||
]},
|
||||
|
10
defs.bzl
10
defs.bzl
@ -1,7 +1,7 @@
|
||||
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
|
||||
load("@bazel_skylib//lib:versions.bzl", "versions")
|
||||
load("@rules_rust//rust:repositories.bzl", "rust_repositories")
|
||||
load("@net_ankiweb_anki//cargo:crates.bzl", "raze_fetch_remote_crates")
|
||||
load("@anki//cargo:crates.bzl", "raze_fetch_remote_crates")
|
||||
load(":python.bzl", "setup_local_python")
|
||||
load(":protobuf.bzl", "setup_protobuf_binary")
|
||||
load("//proto:format.bzl", "setup_clang_format")
|
||||
@ -35,7 +35,7 @@ def setup_deps():
|
||||
|
||||
pip_import(
|
||||
name = "py_deps",
|
||||
requirements = "@net_ankiweb_anki//pip:requirements.txt",
|
||||
requirements = "@anki//pip:requirements.txt",
|
||||
python_runtime = "@python//:python",
|
||||
)
|
||||
|
||||
@ -44,12 +44,12 @@ def setup_deps():
|
||||
python_runtime = "@python//:python",
|
||||
)
|
||||
|
||||
node_repositories(package_json = ["@net_ankiweb_anki//ts:package.json"])
|
||||
node_repositories(package_json = ["@anki//ts:package.json"])
|
||||
|
||||
yarn_install(
|
||||
name = "npm",
|
||||
package_json = "@net_ankiweb_anki//ts:package.json",
|
||||
yarn_lock = "@net_ankiweb_anki//ts:yarn.lock",
|
||||
package_json = "@anki//ts:package.json",
|
||||
yarn_lock = "@anki//ts:yarn.lock",
|
||||
)
|
||||
|
||||
sass_repositories()
|
||||
|
@ -74,14 +74,14 @@ index eff3d9df2..fb2e9f7fe 100644
|
||||
python_runtime = "@python//:python",
|
||||
)
|
||||
|
||||
- node_repositories(package_json = ["@net_ankiweb_anki//ts:package.json"])
|
||||
- node_repositories(package_json = ["@anki//ts:package.json"])
|
||||
+ native.local_repository(
|
||||
+ name = "local_node",
|
||||
+ path = "local_node",
|
||||
+ )
|
||||
+
|
||||
+ node_repositories(
|
||||
+ package_json = ["@net_ankiweb_anki//ts:package.json"],
|
||||
+ package_json = ["@anki//ts:package.json"],
|
||||
+ vendored_node = "@local_node//:node",
|
||||
+ )
|
||||
|
||||
|
0
proto/.top_level
Normal file
0
proto/.top_level
Normal file
@ -6,13 +6,27 @@ load("//proto:clang_format.bzl", "proto_format")
|
||||
|
||||
proto_format(
|
||||
name = "format",
|
||||
srcs = ["backend.proto"],
|
||||
srcs = glob(["**/*.proto"]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
proto_library(
|
||||
name = "backend_proto_lib",
|
||||
srcs = ["backend.proto"],
|
||||
srcs = glob(["**/*.proto"]),
|
||||
# "" removes the "proto/" prefix
|
||||
strip_import_prefix = "",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
exports_files(["backend.proto"])
|
||||
filegroup(
|
||||
name = "proto",
|
||||
srcs = glob(["**/*.proto"]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
exports_files([
|
||||
# for external workspace use
|
||||
"format.py",
|
||||
# an empty file we use to get the root proto/ path in the Rust build
|
||||
".top_level",
|
||||
])
|
||||
|
@ -1,59 +1,11 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package BackendProto;
|
||||
package anki.backend;
|
||||
|
||||
// Generic containers
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
message Empty {}
|
||||
|
||||
message OptionalInt32 {
|
||||
sint32 val = 1;
|
||||
}
|
||||
|
||||
message OptionalUInt32 {
|
||||
uint32 val = 1;
|
||||
}
|
||||
|
||||
message Int32 {
|
||||
sint32 val = 1;
|
||||
}
|
||||
|
||||
message UInt32 {
|
||||
uint32 val = 1;
|
||||
}
|
||||
|
||||
message Int64 {
|
||||
int64 val = 1;
|
||||
}
|
||||
|
||||
message String {
|
||||
string val = 1;
|
||||
}
|
||||
|
||||
message Json {
|
||||
bytes json = 1;
|
||||
}
|
||||
|
||||
message Bool {
|
||||
bool val = 1;
|
||||
}
|
||||
|
||||
message StringList {
|
||||
repeated string vals = 1;
|
||||
}
|
||||
|
||||
message OpChangesWithCount {
|
||||
uint32 count = 1;
|
||||
OpChanges changes = 2;
|
||||
}
|
||||
|
||||
message OpChangesWithId {
|
||||
int64 id = 1;
|
||||
OpChanges changes = 2;
|
||||
}
|
||||
import "anki/generic.proto";
|
||||
|
||||
// IDs used in RPC calls
|
||||
///////////////////////////////////////////////////////////
|
||||
@ -115,13 +67,13 @@ enum ServiceIndex {
|
||||
}
|
||||
|
||||
service SchedulingService {
|
||||
rpc SchedTimingToday(Empty) returns (SchedTimingTodayResponse);
|
||||
rpc StudiedToday(Empty) returns (String);
|
||||
rpc StudiedTodayMessage(StudiedTodayMessageRequest) returns (String);
|
||||
rpc UpdateStats(UpdateStatsRequest) returns (Empty);
|
||||
rpc ExtendLimits(ExtendLimitsRequest) returns (Empty);
|
||||
rpc SchedTimingToday(generic.Empty) returns (SchedTimingTodayResponse);
|
||||
rpc StudiedToday(generic.Empty) returns (generic.String);
|
||||
rpc StudiedTodayMessage(StudiedTodayMessageRequest) returns (generic.String);
|
||||
rpc UpdateStats(UpdateStatsRequest) returns (generic.Empty);
|
||||
rpc ExtendLimits(ExtendLimitsRequest) returns (generic.Empty);
|
||||
rpc CountsForDeckToday(DeckId) returns (CountsForDeckTodayResponse);
|
||||
rpc CongratsInfo(Empty) returns (CongratsInfoResponse);
|
||||
rpc CongratsInfo(generic.Empty) returns (CongratsInfoResponse);
|
||||
rpc RestoreBuriedAndSuspendedCards(CardIds) returns (OpChanges);
|
||||
rpc UnburyDeck(UnburyDeckRequest) returns (OpChanges);
|
||||
rpc BuryOrSuspendCards(BuryOrSuspendCardsRequest)
|
||||
@ -133,35 +85,35 @@ service SchedulingService {
|
||||
rpc SortCards(SortCardsRequest) returns (OpChangesWithCount);
|
||||
rpc SortDeck(SortDeckRequest) returns (OpChangesWithCount);
|
||||
rpc GetNextCardStates(CardId) returns (NextCardStates);
|
||||
rpc DescribeNextStates(NextCardStates) returns (StringList);
|
||||
rpc StateIsLeech(SchedulingState) returns (Bool);
|
||||
rpc DescribeNextStates(NextCardStates) returns (generic.StringList);
|
||||
rpc StateIsLeech(SchedulingState) returns (generic.Bool);
|
||||
rpc AnswerCard(CardAnswer) returns (OpChanges);
|
||||
rpc UpgradeScheduler(Empty) returns (Empty);
|
||||
rpc UpgradeScheduler(generic.Empty) returns (generic.Empty);
|
||||
rpc GetQueuedCards(GetQueuedCardsRequest) returns (QueuedCards);
|
||||
}
|
||||
|
||||
service DecksService {
|
||||
rpc AddDeckLegacy(Json) returns (OpChangesWithId);
|
||||
rpc AddDeckLegacy(generic.Json) returns (OpChangesWithId);
|
||||
rpc AddOrUpdateDeckLegacy(AddOrUpdateDeckLegacyRequest) returns (DeckId);
|
||||
rpc DeckTree(DeckTreeRequest) returns (DeckTreeNode);
|
||||
rpc DeckTreeLegacy(Empty) returns (Json);
|
||||
rpc GetAllDecksLegacy(Empty) returns (Json);
|
||||
rpc GetDeckIdByName(String) returns (DeckId);
|
||||
rpc DeckTreeLegacy(generic.Empty) returns (generic.Json);
|
||||
rpc GetAllDecksLegacy(generic.Empty) returns (generic.Json);
|
||||
rpc GetDeckIdByName(generic.String) returns (DeckId);
|
||||
rpc GetDeck(DeckId) returns (Deck);
|
||||
rpc UpdateDeck(Deck) returns (OpChanges);
|
||||
rpc UpdateDeckLegacy(Json) returns (OpChanges);
|
||||
rpc UpdateDeckLegacy(generic.Json) returns (OpChanges);
|
||||
rpc SetDeckCollapsed(SetDeckCollapsedRequest) returns (OpChanges);
|
||||
rpc GetDeckLegacy(DeckId) returns (Json);
|
||||
rpc GetDeckLegacy(DeckId) returns (generic.Json);
|
||||
rpc GetDeckNames(GetDeckNamesRequest) returns (DeckNames);
|
||||
rpc NewDeckLegacy(Bool) returns (Json);
|
||||
rpc NewDeckLegacy(generic.Bool) returns (generic.Json);
|
||||
rpc RemoveDecks(DeckIds) returns (OpChangesWithCount);
|
||||
rpc ReparentDecks(ReparentDecksRequest) returns (OpChangesWithCount);
|
||||
rpc RenameDeck(RenameDeckRequest) returns (OpChanges);
|
||||
rpc GetOrCreateFilteredDeck(DeckId) returns (FilteredDeckForUpdate);
|
||||
rpc AddOrUpdateFilteredDeck(FilteredDeckForUpdate) returns (OpChangesWithId);
|
||||
rpc FilteredDeckOrderLabels(Empty) returns (StringList);
|
||||
rpc FilteredDeckOrderLabels(generic.Empty) returns (generic.StringList);
|
||||
rpc SetCurrentDeck(DeckId) returns (OpChanges);
|
||||
rpc GetCurrentDeck(Empty) returns (Deck);
|
||||
rpc GetCurrentDeck(generic.Empty) returns (Deck);
|
||||
}
|
||||
|
||||
service NotesService {
|
||||
@ -181,47 +133,48 @@ service NotesService {
|
||||
}
|
||||
|
||||
service SyncService {
|
||||
rpc SyncMedia(SyncAuth) returns (Empty);
|
||||
rpc AbortSync(Empty) returns (Empty);
|
||||
rpc AbortMediaSync(Empty) returns (Empty);
|
||||
rpc BeforeUpload(Empty) returns (Empty);
|
||||
rpc SyncMedia(SyncAuth) returns (generic.Empty);
|
||||
rpc AbortSync(generic.Empty) returns (generic.Empty);
|
||||
rpc AbortMediaSync(generic.Empty) returns (generic.Empty);
|
||||
rpc BeforeUpload(generic.Empty) returns (generic.Empty);
|
||||
rpc SyncLogin(SyncLoginRequest) returns (SyncAuth);
|
||||
rpc SyncStatus(SyncAuth) returns (SyncStatusResponse);
|
||||
rpc SyncCollection(SyncAuth) returns (SyncCollectionResponse);
|
||||
rpc FullUpload(SyncAuth) returns (Empty);
|
||||
rpc FullDownload(SyncAuth) returns (Empty);
|
||||
rpc SyncServerMethod(SyncServerMethodRequest) returns (Json);
|
||||
rpc FullUpload(SyncAuth) returns (generic.Empty);
|
||||
rpc FullDownload(SyncAuth) returns (generic.Empty);
|
||||
rpc SyncServerMethod(SyncServerMethodRequest) returns (generic.Json);
|
||||
}
|
||||
|
||||
service ConfigService {
|
||||
rpc GetConfigJson(String) returns (Json);
|
||||
rpc GetConfigJson(generic.String) returns (generic.Json);
|
||||
rpc SetConfigJson(SetConfigJsonRequest) returns (OpChanges);
|
||||
rpc SetConfigJsonNoUndo(SetConfigJsonRequest) returns (Empty);
|
||||
rpc RemoveConfig(String) returns (OpChanges);
|
||||
rpc GetAllConfig(Empty) returns (Json);
|
||||
rpc GetConfigBool(Config.Bool) returns (Bool);
|
||||
rpc SetConfigJsonNoUndo(SetConfigJsonRequest) returns (generic.Empty);
|
||||
rpc RemoveConfig(generic.String) returns (OpChanges);
|
||||
rpc GetAllConfig(generic.Empty) returns (generic.Json);
|
||||
rpc GetConfigBool(Config.Bool) returns (generic.Bool);
|
||||
rpc SetConfigBool(SetConfigBoolRequest) returns (OpChanges);
|
||||
rpc GetConfigString(Config.String) returns (String);
|
||||
rpc GetConfigString(Config.String) returns (generic.String);
|
||||
rpc SetConfigString(SetConfigStringRequest) returns (OpChanges);
|
||||
rpc GetPreferences(Empty) returns (Preferences);
|
||||
rpc GetPreferences(generic.Empty) returns (Preferences);
|
||||
rpc SetPreferences(Preferences) returns (OpChanges);
|
||||
}
|
||||
|
||||
service NotetypesService {
|
||||
rpc AddNotetype(Notetype) returns (OpChangesWithId);
|
||||
rpc UpdateNotetype(Notetype) returns (OpChanges);
|
||||
rpc AddNotetypeLegacy(Json) returns (OpChangesWithId);
|
||||
rpc UpdateNotetypeLegacy(Json) returns (OpChanges);
|
||||
rpc AddNotetypeLegacy(generic.Json) returns (OpChangesWithId);
|
||||
rpc UpdateNotetypeLegacy(generic.Json) returns (OpChanges);
|
||||
rpc AddOrUpdateNotetype(AddOrUpdateNotetypeRequest) returns (NotetypeId);
|
||||
rpc GetStockNotetypeLegacy(StockNotetype) returns (Json);
|
||||
rpc GetStockNotetypeLegacy(StockNotetype) returns (generic.Json);
|
||||
rpc GetNotetype(NotetypeId) returns (Notetype);
|
||||
rpc GetNotetypeLegacy(NotetypeId) returns (Json);
|
||||
rpc GetNotetypeNames(Empty) returns (NotetypeNames);
|
||||
rpc GetNotetypeNamesAndCounts(Empty) returns (NotetypeUseCounts);
|
||||
rpc GetNotetypeIdByName(String) returns (NotetypeId);
|
||||
rpc GetNotetypeLegacy(NotetypeId) returns (generic.Json);
|
||||
rpc GetNotetypeNames(generic.Empty) returns (NotetypeNames);
|
||||
rpc GetNotetypeNamesAndCounts(generic.Empty) returns (NotetypeUseCounts);
|
||||
rpc GetNotetypeIdByName(generic.String) returns (NotetypeId);
|
||||
rpc RemoveNotetype(NotetypeId) returns (OpChanges);
|
||||
rpc GetAuxNotetypeConfigKey(GetAuxConfigKeyRequest) returns (String);
|
||||
rpc GetAuxTemplateConfigKey(GetAuxTemplateConfigKeyRequest) returns (String);
|
||||
rpc GetAuxNotetypeConfigKey(GetAuxConfigKeyRequest) returns (generic.String);
|
||||
rpc GetAuxTemplateConfigKey(GetAuxTemplateConfigKeyRequest)
|
||||
returns (generic.String);
|
||||
rpc GetSingleNotetypeOfNotes(NoteIds) returns (NotetypeId);
|
||||
rpc GetChangeNotetypeInfo(GetChangeNotetypeInfoRequest)
|
||||
returns (ChangeNotetypeInfo);
|
||||
@ -231,34 +184,34 @@ service NotetypesService {
|
||||
service CardRenderingService {
|
||||
rpc ExtractAVTags(ExtractAVTagsRequest) returns (ExtractAVTagsResponse);
|
||||
rpc ExtractLatex(ExtractLatexRequest) returns (ExtractLatexResponse);
|
||||
rpc GetEmptyCards(Empty) returns (EmptyCardsReport);
|
||||
rpc GetEmptyCards(generic.Empty) returns (EmptyCardsReport);
|
||||
rpc RenderExistingCard(RenderExistingCardRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc RenderUncommittedCard(RenderUncommittedCardRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc RenderUncommittedCardLegacy(RenderUncommittedCardLegacyRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc StripAVTags(String) returns (String);
|
||||
rpc RenderMarkdown(RenderMarkdownRequest) returns (String);
|
||||
rpc StripAVTags(generic.String) returns (generic.String);
|
||||
rpc RenderMarkdown(RenderMarkdownRequest) returns (generic.String);
|
||||
}
|
||||
|
||||
service DeckConfigService {
|
||||
rpc AddOrUpdateDeckConfigLegacy(Json) returns (DeckConfigId);
|
||||
rpc AddOrUpdateDeckConfigLegacy(generic.Json) returns (DeckConfigId);
|
||||
rpc GetDeckConfig(DeckConfigId) returns (DeckConfig);
|
||||
rpc AllDeckConfigLegacy(Empty) returns (Json);
|
||||
rpc GetDeckConfigLegacy(DeckConfigId) returns (Json);
|
||||
rpc NewDeckConfigLegacy(Empty) returns (Json);
|
||||
rpc RemoveDeckConfig(DeckConfigId) returns (Empty);
|
||||
rpc AllDeckConfigLegacy(generic.Empty) returns (generic.Json);
|
||||
rpc GetDeckConfigLegacy(DeckConfigId) returns (generic.Json);
|
||||
rpc NewDeckConfigLegacy(generic.Empty) returns (generic.Json);
|
||||
rpc RemoveDeckConfig(DeckConfigId) returns (generic.Empty);
|
||||
rpc GetDeckConfigsForUpdate(DeckId) returns (DeckConfigsForUpdate);
|
||||
rpc UpdateDeckConfigs(UpdateDeckConfigsRequest) returns (OpChanges);
|
||||
}
|
||||
|
||||
service TagsService {
|
||||
rpc ClearUnusedTags(Empty) returns (OpChangesWithCount);
|
||||
rpc AllTags(Empty) returns (StringList);
|
||||
rpc RemoveTags(String) returns (OpChangesWithCount);
|
||||
rpc ClearUnusedTags(generic.Empty) returns (OpChangesWithCount);
|
||||
rpc AllTags(generic.Empty) returns (generic.StringList);
|
||||
rpc RemoveTags(generic.String) returns (OpChangesWithCount);
|
||||
rpc SetTagCollapsed(SetTagCollapsedRequest) returns (OpChanges);
|
||||
rpc TagTree(Empty) returns (TagTreeNode);
|
||||
rpc TagTree(generic.Empty) returns (TagTreeNode);
|
||||
rpc ReparentTags(ReparentTagsRequest) returns (OpChangesWithCount);
|
||||
rpc RenameTags(RenameTagsRequest) returns (OpChangesWithCount);
|
||||
rpc AddNoteTags(NoteIdsAndTagsRequest) returns (OpChangesWithCount);
|
||||
@ -267,55 +220,49 @@ service TagsService {
|
||||
}
|
||||
|
||||
service SearchService {
|
||||
rpc BuildSearchString(SearchNode) returns (String);
|
||||
rpc BuildSearchString(SearchNode) returns (generic.String);
|
||||
rpc SearchCards(SearchRequest) returns (SearchResponse);
|
||||
rpc SearchNotes(SearchRequest) returns (SearchResponse);
|
||||
rpc JoinSearchNodes(JoinSearchNodesRequest) returns (String);
|
||||
rpc ReplaceSearchNode(ReplaceSearchNodeRequest) returns (String);
|
||||
rpc JoinSearchNodes(JoinSearchNodesRequest) returns (generic.String);
|
||||
rpc ReplaceSearchNode(ReplaceSearchNodeRequest) returns (generic.String);
|
||||
rpc FindAndReplace(FindAndReplaceRequest) returns (OpChangesWithCount);
|
||||
rpc AllBrowserColumns(Empty) returns (BrowserColumns);
|
||||
rpc BrowserRowForId(Int64) returns (BrowserRow);
|
||||
rpc SetActiveBrowserColumns(StringList) returns (Empty);
|
||||
rpc AllBrowserColumns(generic.Empty) returns (BrowserColumns);
|
||||
rpc BrowserRowForId(generic.Int64) returns (BrowserRow);
|
||||
rpc SetActiveBrowserColumns(generic.StringList) returns (generic.Empty);
|
||||
}
|
||||
|
||||
service StatsService {
|
||||
rpc CardStats(CardId) returns (String);
|
||||
rpc CardStats(CardId) returns (generic.String);
|
||||
rpc Graphs(GraphsRequest) returns (GraphsResponse);
|
||||
rpc GetGraphPreferences(Empty) returns (GraphPreferences);
|
||||
rpc SetGraphPreferences(GraphPreferences) returns (Empty);
|
||||
rpc GetGraphPreferences(generic.Empty) returns (GraphPreferences);
|
||||
rpc SetGraphPreferences(GraphPreferences) returns (generic.Empty);
|
||||
}
|
||||
|
||||
service MediaService {
|
||||
rpc CheckMedia(Empty) returns (CheckMediaResponse);
|
||||
rpc TrashMediaFiles(TrashMediaFilesRequest) returns (Empty);
|
||||
rpc AddMediaFile(AddMediaFileRequest) returns (String);
|
||||
rpc EmptyTrash(Empty) returns (Empty);
|
||||
rpc RestoreTrash(Empty) returns (Empty);
|
||||
}
|
||||
|
||||
service I18nService {
|
||||
rpc TranslateString(TranslateStringRequest) returns (String);
|
||||
rpc FormatTimespan(FormatTimespanRequest) returns (String);
|
||||
rpc I18nResources(I18nResourcesRequest) returns (Json);
|
||||
rpc CheckMedia(generic.Empty) returns (CheckMediaResponse);
|
||||
rpc TrashMediaFiles(TrashMediaFilesRequest) returns (generic.Empty);
|
||||
rpc AddMediaFile(AddMediaFileRequest) returns (generic.String);
|
||||
rpc EmptyTrash(generic.Empty) returns (generic.Empty);
|
||||
rpc RestoreTrash(generic.Empty) returns (generic.Empty);
|
||||
}
|
||||
|
||||
service CollectionService {
|
||||
rpc OpenCollection(OpenCollectionRequest) returns (Empty);
|
||||
rpc CloseCollection(CloseCollectionRequest) returns (Empty);
|
||||
rpc CheckDatabase(Empty) returns (CheckDatabaseResponse);
|
||||
rpc GetUndoStatus(Empty) returns (UndoStatus);
|
||||
rpc Undo(Empty) returns (OpChangesAfterUndo);
|
||||
rpc Redo(Empty) returns (OpChangesAfterUndo);
|
||||
rpc AddCustomUndoEntry(String) returns (UInt32);
|
||||
rpc MergeUndoEntries(UInt32) returns (OpChanges);
|
||||
rpc LatestProgress(Empty) returns (Progress);
|
||||
rpc SetWantsAbort(Empty) returns (Empty);
|
||||
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 (Empty);
|
||||
rpc RemoveCards(RemoveCardsRequest) returns (generic.Empty);
|
||||
rpc SetDeck(SetDeckRequest) returns (OpChangesWithCount);
|
||||
rpc SetFlag(SetFlagRequest) returns (OpChangesWithCount);
|
||||
}
|
||||
@ -525,7 +472,7 @@ message Notetype {
|
||||
|
||||
bytes other = 255;
|
||||
}
|
||||
OptionalUInt32 ord = 1;
|
||||
generic.OptionalUInt32 ord = 1;
|
||||
string name = 2;
|
||||
Config config = 5;
|
||||
}
|
||||
@ -542,7 +489,7 @@ message Notetype {
|
||||
bytes other = 255;
|
||||
}
|
||||
|
||||
OptionalUInt32 ord = 1;
|
||||
generic.OptionalUInt32 ord = 1;
|
||||
string name = 2;
|
||||
int64 mtime_secs = 3;
|
||||
sint32 usn = 4;
|
||||
@ -661,7 +608,7 @@ message Progress {
|
||||
uint32 stage_current = 3;
|
||||
}
|
||||
oneof value {
|
||||
Empty none = 1;
|
||||
generic.Empty none = 1;
|
||||
MediaSync media_sync = 2;
|
||||
string media_check = 3;
|
||||
FullSync full_sync = 4;
|
||||
@ -797,34 +744,6 @@ message TrashMediaFilesRequest {
|
||||
repeated string fnames = 1;
|
||||
}
|
||||
|
||||
message TranslateStringRequest {
|
||||
uint32 module_index = 1;
|
||||
uint32 message_index = 2;
|
||||
map<string, TranslateArgValue> args = 3;
|
||||
}
|
||||
|
||||
message TranslateArgValue {
|
||||
oneof value {
|
||||
string str = 1;
|
||||
double number = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message FormatTimespanRequest {
|
||||
enum Context {
|
||||
PRECISE = 0;
|
||||
ANSWER_BUTTONS = 1;
|
||||
INTERVALS = 2;
|
||||
}
|
||||
|
||||
float seconds = 1;
|
||||
Context context = 2;
|
||||
}
|
||||
|
||||
message I18nResourcesRequest {
|
||||
repeated string modules = 1;
|
||||
}
|
||||
|
||||
message StudiedTodayMessageRequest {
|
||||
uint32 cards = 1;
|
||||
double seconds = 2;
|
||||
@ -857,7 +776,7 @@ message SortOrder {
|
||||
bool reverse = 2;
|
||||
}
|
||||
oneof value {
|
||||
Empty none = 1;
|
||||
generic.Empty none = 1;
|
||||
string custom = 2;
|
||||
Builtin builtin = 3;
|
||||
}
|
||||
@ -1606,6 +1525,16 @@ message OpChanges {
|
||||
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;
|
44
proto/anki/generic.proto
Normal file
44
proto/anki/generic.proto
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.generic;
|
||||
|
||||
message Empty {}
|
||||
|
||||
message OptionalInt32 {
|
||||
sint32 val = 1;
|
||||
}
|
||||
|
||||
message OptionalUInt32 {
|
||||
uint32 val = 1;
|
||||
}
|
||||
|
||||
message Int32 {
|
||||
sint32 val = 1;
|
||||
}
|
||||
|
||||
message UInt32 {
|
||||
uint32 val = 1;
|
||||
}
|
||||
|
||||
message Int64 {
|
||||
int64 val = 1;
|
||||
}
|
||||
|
||||
message String {
|
||||
string val = 1;
|
||||
}
|
||||
|
||||
message Json {
|
||||
bytes json = 1;
|
||||
}
|
||||
|
||||
message Bool {
|
||||
bool val = 1;
|
||||
}
|
||||
|
||||
message StringList {
|
||||
repeated string vals = 1;
|
||||
}
|
42
proto/anki/i18n.proto
Normal file
42
proto/anki/i18n.proto
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.i18n;
|
||||
|
||||
import "anki/generic.proto";
|
||||
|
||||
service I18nService {
|
||||
rpc TranslateString(TranslateStringRequest) returns (generic.String);
|
||||
rpc FormatTimespan(FormatTimespanRequest) returns (generic.String);
|
||||
rpc I18nResources(I18nResourcesRequest) returns (generic.Json);
|
||||
}
|
||||
|
||||
message TranslateStringRequest {
|
||||
uint32 module_index = 1;
|
||||
uint32 message_index = 2;
|
||||
map<string, TranslateArgValue> args = 3;
|
||||
}
|
||||
|
||||
message TranslateArgValue {
|
||||
oneof value {
|
||||
string str = 1;
|
||||
double number = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message FormatTimespanRequest {
|
||||
enum Context {
|
||||
PRECISE = 0;
|
||||
ANSWER_BUTTONS = 1;
|
||||
INTERVALS = 2;
|
||||
}
|
||||
|
||||
float seconds = 1;
|
||||
Context context = 2;
|
||||
}
|
||||
|
||||
message I18nResourcesRequest {
|
||||
repeated string modules = 1;
|
||||
}
|
@ -14,9 +14,9 @@ def _impl(rctx):
|
||||
alias(
|
||||
name = "clang_format",
|
||||
actual = select({
|
||||
"@net_ankiweb_anki//platforms:windows_x86_64": "@clang_format_windows_x86_64//:clang-format.exe",
|
||||
"@net_ankiweb_anki//platforms:macos_x86_64": "@clang_format_macos_x86_64//:clang-format",
|
||||
"@net_ankiweb_anki//platforms:linux_x86_64": "@clang_format_linux_x86_64//:clang-format",
|
||||
"@anki//platforms:windows_x86_64": "@clang_format_windows_x86_64//:clang-format.exe",
|
||||
"@anki//platforms:macos_x86_64": "@clang_format_macos_x86_64//:clang-format",
|
||||
"@anki//platforms:linux_x86_64": "@clang_format_linux_x86_64//:clang-format",
|
||||
}),
|
||||
visibility = ["//visibility:public"]
|
||||
)
|
||||
@ -68,7 +68,7 @@ def proto_format(name, srcs, **kwargs):
|
||||
py_test(
|
||||
name = name,
|
||||
srcs = [
|
||||
"format.py",
|
||||
"@anki//proto:format.py",
|
||||
],
|
||||
data = ["@clang_format//:clang_format"] + srcs,
|
||||
args = ["$(location @clang_format//:clang_format)"] + [native.package_name() + "/" + f for f in srcs],
|
||||
|
@ -14,9 +14,9 @@ def _impl(rctx):
|
||||
alias(
|
||||
name = "clang_format",
|
||||
actual = select({
|
||||
"@net_ankiweb_anki//platforms:windows_x86_64": "@clang_format_windows_x86_64//:clang-format.exe",
|
||||
"@net_ankiweb_anki//platforms:macos_x86_64": "@clang_format_macos_x86_64//:clang-format",
|
||||
"@net_ankiweb_anki//platforms:linux_x86_64": "@clang_format_linux_x86_64//:clang-format",
|
||||
"@anki//platforms:windows_x86_64": "@clang_format_windows_x86_64//:clang-format.exe",
|
||||
"@anki//platforms:macos_x86_64": "@clang_format_macos_x86_64//:clang-format",
|
||||
"@anki//platforms:linux_x86_64": "@clang_format_linux_x86_64//:clang-format",
|
||||
}),
|
||||
visibility = ["//visibility:public"]
|
||||
)
|
||||
@ -68,7 +68,7 @@ def proto_format(name, srcs, **kwargs):
|
||||
py_test(
|
||||
name = name,
|
||||
srcs = [
|
||||
"format.py",
|
||||
"@anki//format.py",
|
||||
],
|
||||
data = ["@clang_format//:clang_format"] + srcs,
|
||||
args = ["$(location @clang_format//:clang_format)"] + [native.package_name() + "/" + f for f in srcs],
|
||||
|
@ -12,10 +12,10 @@ def _impl(rctx):
|
||||
alias(
|
||||
name = "protoc",
|
||||
actual = select({
|
||||
"@net_ankiweb_anki//platforms:windows_x86_64": "@protoc_bin_windows//:bin/protoc.exe",
|
||||
"@net_ankiweb_anki//platforms:macos_x86_64": "@protoc_bin_macos//:bin/protoc",
|
||||
"@net_ankiweb_anki//platforms:linux_x86_64": "@protoc_bin_linux_x86_64//:bin/protoc",
|
||||
"@net_ankiweb_anki//platforms:linux_arm64": "@protoc_bin_linux_arm64//:bin/protoc"
|
||||
"@anki//platforms:windows_x86_64": "@protoc_bin_windows//:bin/protoc.exe",
|
||||
"@anki//platforms:macos_x86_64": "@protoc_bin_macos//:bin/protoc",
|
||||
"@anki//platforms:linux_x86_64": "@protoc_bin_linux_x86_64//:bin/protoc",
|
||||
"@anki//platforms:linux_arm64": "@protoc_bin_linux_arm64//:bin/protoc"
|
||||
}),
|
||||
visibility = ["//visibility:public"]
|
||||
)
|
||||
|
@ -32,6 +32,7 @@ py_library(
|
||||
"py.typed",
|
||||
":buildinfo",
|
||||
":hooks_gen",
|
||||
":proto",
|
||||
"//pylib/anki/_backend",
|
||||
],
|
||||
imports = [
|
||||
@ -105,3 +106,30 @@ filegroup(
|
||||
"//pylib:__subpackages__",
|
||||
],
|
||||
)
|
||||
|
||||
load("//pylib:protobuf.bzl", "py_proto")
|
||||
|
||||
py_proto(
|
||||
name = "proto_files",
|
||||
srcs = ["//proto"],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "proto",
|
||||
srcs = [
|
||||
# "__init__.py",
|
||||
":proto_files",
|
||||
],
|
||||
visibility = ["//pylib:__subpackages__"],
|
||||
)
|
||||
|
||||
# only used for genbackend.py
|
||||
py_library(
|
||||
name = "proto_lib",
|
||||
srcs = [":proto"],
|
||||
imports = [".."],
|
||||
visibility = ["//pylib:__subpackages__"],
|
||||
)
|
||||
|
@ -1,27 +1,18 @@
|
||||
load("@rules_python//python:defs.bzl", "py_binary")
|
||||
load("@py_deps//:requirements.bzl", "requirement")
|
||||
load("//pylib:protobuf.bzl", "py_proto_library_typed")
|
||||
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
|
||||
load("@bazel_skylib//lib:selects.bzl", "selects")
|
||||
|
||||
py_proto_library_typed(
|
||||
name = "backend_pb2",
|
||||
src = "//proto:backend.proto",
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
|
||||
py_binary(
|
||||
name = "genbackend",
|
||||
srcs = [
|
||||
"backend_pb2",
|
||||
"genbackend.py",
|
||||
],
|
||||
deps = [
|
||||
requirement("black"),
|
||||
requirement("stringcase"),
|
||||
requirement("protobuf"),
|
||||
"//pylib/anki:proto_lib",
|
||||
],
|
||||
)
|
||||
|
||||
@ -94,7 +85,6 @@ filegroup(
|
||||
srcs = [
|
||||
"__init__.py",
|
||||
"rsbridge.pyi",
|
||||
":backend_pb2",
|
||||
":fluent_gen",
|
||||
":rsbackend_gen",
|
||||
":rsbridge",
|
||||
|
@ -11,6 +11,7 @@ from weakref import ref
|
||||
from markdown import markdown
|
||||
|
||||
import anki.buildinfo
|
||||
from anki import backend_pb2, i18n_pb2
|
||||
from anki._backend.generated import RustBackendGenerated
|
||||
from anki.dbproxy import Row as DBRow
|
||||
from anki.dbproxy import ValueForDB
|
||||
@ -32,7 +33,6 @@ from ..errors import (
|
||||
TemplateError,
|
||||
UndoEmpty,
|
||||
)
|
||||
from . import backend_pb2 as pb
|
||||
from . import rsbridge
|
||||
from .fluent import GeneratedTranslations, LegacyTranslationEnum
|
||||
|
||||
@ -65,7 +65,7 @@ class RustBackend(RustBackendGenerated):
|
||||
if langs is None:
|
||||
langs = [anki.lang.currentLang]
|
||||
|
||||
init_msg = pb.BackendInit(
|
||||
init_msg = backend_pb2.BackendInit(
|
||||
preferred_langs=langs,
|
||||
server=server,
|
||||
)
|
||||
@ -95,7 +95,7 @@ class RustBackend(RustBackendGenerated):
|
||||
return from_json_bytes(self._backend.db_command(to_json_bytes(input)))
|
||||
except Exception as e:
|
||||
err_bytes = bytes(e.args[0])
|
||||
err = pb.BackendError()
|
||||
err = backend_pb2.BackendError()
|
||||
err.ParseFromString(err_bytes)
|
||||
raise backend_exception_to_pylib(err)
|
||||
|
||||
@ -125,21 +125,21 @@ class RustBackend(RustBackendGenerated):
|
||||
return self._backend.command(service, method, input_bytes)
|
||||
except Exception as e:
|
||||
err_bytes = bytes(e.args[0])
|
||||
err = pb.BackendError()
|
||||
err = backend_pb2.BackendError()
|
||||
err.ParseFromString(err_bytes)
|
||||
raise backend_exception_to_pylib(err)
|
||||
|
||||
|
||||
def translate_string_in(
|
||||
module_index: int, message_index: int, **kwargs: Union[str, int, float]
|
||||
) -> pb.TranslateStringRequest:
|
||||
) -> i18n_pb2.TranslateStringRequest:
|
||||
args = {}
|
||||
for (k, v) in kwargs.items():
|
||||
if isinstance(v, str):
|
||||
args[k] = pb.TranslateArgValue(str=v)
|
||||
args[k] = i18n_pb2.TranslateArgValue(str=v)
|
||||
else:
|
||||
args[k] = pb.TranslateArgValue(number=v)
|
||||
return pb.TranslateStringRequest(
|
||||
args[k] = i18n_pb2.TranslateArgValue(number=v)
|
||||
return i18n_pb2.TranslateStringRequest(
|
||||
module_index=module_index, message_index=message_index, args=args
|
||||
)
|
||||
|
||||
@ -167,8 +167,8 @@ class Translations(GeneratedTranslations):
|
||||
)
|
||||
|
||||
|
||||
def backend_exception_to_pylib(err: pb.BackendError) -> Exception:
|
||||
kind = pb.BackendError
|
||||
def backend_exception_to_pylib(err: backend_pb2.BackendError) -> Exception:
|
||||
kind = backend_pb2.BackendError
|
||||
val = err.kind
|
||||
if val == kind.INTERRUPTED:
|
||||
return Interrupted()
|
||||
|
@ -1 +0,0 @@
|
||||
../../../bazel-bin/pylib/anki/_backend/backend_pb2.pyi
|
@ -7,7 +7,10 @@ import re
|
||||
import sys
|
||||
|
||||
import google.protobuf.descriptor
|
||||
import pylib.anki._backend.backend_pb2 as pb
|
||||
|
||||
import anki.backend_pb2
|
||||
import anki.i18n_pb2
|
||||
|
||||
import stringcase
|
||||
|
||||
TYPE_DOUBLE = 1
|
||||
@ -73,11 +76,11 @@ def python_type_inner(field):
|
||||
raise Exception(f"unknown type: {type}")
|
||||
|
||||
|
||||
def fullname(fullname):
|
||||
if "FluentString" in fullname:
|
||||
return fullname.replace("BackendProto", "anki.fluent_pb2")
|
||||
else:
|
||||
return fullname.replace("BackendProto", "pb")
|
||||
def fullname(fullname: str) -> str:
|
||||
# eg anki.generic.Empty -> anki.generic_pb2.Empty
|
||||
components = fullname.split(".")
|
||||
components[1] += "_pb2"
|
||||
return ".".join(components)
|
||||
|
||||
|
||||
# get_deck_i_d -> get_deck_id etc
|
||||
@ -131,7 +134,7 @@ def render_method(service_idx, method_idx, method):
|
||||
return_type = python_type(f)
|
||||
else:
|
||||
single_field = ""
|
||||
return_type = f"pb.{method.output_type.name}"
|
||||
return_type = fullname(method.output_type.full_name)
|
||||
|
||||
if method.name in SKIP_DECODE:
|
||||
return_type = "bytes"
|
||||
@ -144,7 +147,7 @@ def render_method(service_idx, method_idx, method):
|
||||
buf += f"""return self._run_command({service_idx}, {method_idx}, input)
|
||||
"""
|
||||
else:
|
||||
buf += f"""output = pb.{method.output_type.name}()
|
||||
buf += f"""output = {fullname(method.output_type.full_name)}()
|
||||
output.ParseFromString(self._run_command({service_idx}, {method_idx}, input))
|
||||
return output{single_field}
|
||||
"""
|
||||
@ -162,12 +165,14 @@ def render_service(
|
||||
out.append(render_method(service_index, method_index, method))
|
||||
|
||||
|
||||
for service in pb.ServiceIndex.DESCRIPTOR.values:
|
||||
service_modules = dict(I18N="i18n")
|
||||
|
||||
for service in anki.backend_pb2.ServiceIndex.DESCRIPTOR.values:
|
||||
# SERVICE_INDEX_TEST -> _TESTSERVICE
|
||||
service_var = (
|
||||
"_" + service.name.replace("SERVICE_INDEX", "").replace("_", "") + "SERVICE"
|
||||
)
|
||||
service_obj = getattr(pb, service_var)
|
||||
base = service.name.replace("SERVICE_INDEX_", "")
|
||||
service_pkg = (service_modules.get(base) or "backend") + ""
|
||||
service_var = "_" + base.replace("_", "") + "SERVICE"
|
||||
service_obj = getattr(getattr(anki, service_pkg + "_pb2"), service_var)
|
||||
service_index = service.number
|
||||
render_service(service_obj, service_index)
|
||||
|
||||
@ -194,7 +199,7 @@ col.decks.all_config()
|
||||
|
||||
from typing import *
|
||||
|
||||
import anki._backend.backend_pb2 as pb
|
||||
import anki
|
||||
|
||||
class RustBackendGenerated:
|
||||
def _run_command(self, service: int, method: int, input: Any) -> bytes:
|
||||
|
1
pylib/anki/backend_pb2.pyi
Symbolic link
1
pylib/anki/backend_pb2.pyi
Symbolic link
@ -0,0 +1 @@
|
||||
../../bazel-bin/pylib/anki/backend_pb2.pyi
|
@ -10,7 +10,7 @@ import time
|
||||
from typing import List, NewType, Optional
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki._legacy import DeprecatedNamesMixin, deprecated
|
||||
from anki.consts import *
|
||||
|
@ -7,7 +7,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any, Generator, List, Literal, Optional, Sequence, Tuple, Union, cast
|
||||
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
|
||||
# protobuf we publicly export - listed first to avoid circular imports
|
||||
from anki._legacy import DeprecatedNamesMixin, deprecated
|
||||
@ -35,7 +35,7 @@ import weakref
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
import anki.latex
|
||||
from anki import hooks
|
||||
from anki import generic_pb2, hooks
|
||||
from anki._backend import RustBackend, Translations
|
||||
from anki.browser import BrowserConfig, BrowserDefaults
|
||||
from anki.cards import Card, CardId
|
||||
@ -492,7 +492,7 @@ class Collection(DeprecatedNamesMixin):
|
||||
return _pb.SortOrder(custom=order)
|
||||
if isinstance(order, bool):
|
||||
if order is False:
|
||||
return _pb.SortOrder(none=_pb.Empty())
|
||||
return _pb.SortOrder(none=generic_pb2.Empty())
|
||||
# order=True: set args to sort column and reverse from config
|
||||
sort_key = BrowserConfig.sort_column_key(finding_notes)
|
||||
order = self.get_browser_column(self.get_config(sort_key))
|
||||
@ -506,7 +506,7 @@ class Collection(DeprecatedNamesMixin):
|
||||
|
||||
# eg, user is ordering on an add-on field with the add-on not installed
|
||||
print(f"{order} is not a valid sort order.")
|
||||
return _pb.SortOrder(none=_pb.Empty())
|
||||
return _pb.SortOrder(none=generic_pb2.Empty())
|
||||
|
||||
def find_and_replace(
|
||||
self,
|
||||
|
@ -25,7 +25,7 @@ from typing import Any
|
||||
from weakref import ref
|
||||
|
||||
import anki
|
||||
from anki._backend import backend_pb2 as _pb
|
||||
from anki import backend_pb2 as _pb
|
||||
from anki.collection import OpChanges
|
||||
from anki.errors import NotFoundError
|
||||
from anki.utils import from_json_bytes, to_json_bytes
|
||||
|
@ -23,7 +23,7 @@ from typing import (
|
||||
if TYPE_CHECKING:
|
||||
import anki
|
||||
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki._legacy import DeprecatedNamesMixin, deprecated, print_deprecation_warning
|
||||
from anki.cards import CardId
|
||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
||||
|
1
pylib/anki/generic_pb2.pyi
Symbolic link
1
pylib/anki/generic_pb2.pyi
Symbolic link
@ -0,0 +1 @@
|
||||
../../bazel-bin/pylib/anki/generic_pb2.pyi
|
1
pylib/anki/i18n_pb2.pyi
Symbolic link
1
pylib/anki/i18n_pb2.pyi
Symbolic link
@ -0,0 +1 @@
|
||||
../../bazel-bin/pylib/anki/i18n_pb2.pyi
|
@ -9,7 +9,8 @@ import weakref
|
||||
from typing import Optional, Tuple
|
||||
|
||||
import anki
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki._backend
|
||||
import anki.i18n_pb2 as _pb
|
||||
|
||||
# public exports
|
||||
TR = anki._backend.LegacyTranslationEnum
|
||||
|
@ -10,7 +10,7 @@ from dataclasses import dataclass
|
||||
from typing import Any, List, Optional, Tuple
|
||||
|
||||
import anki
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki.models import NotetypeDict
|
||||
from anki.template import TemplateRenderContext, TemplateRenderOutput
|
||||
|
@ -11,7 +11,7 @@ import time
|
||||
from typing import Any, Callable, List, Optional, Tuple
|
||||
|
||||
import anki
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki._legacy import deprecated
|
||||
from anki.consts import *
|
||||
from anki.latex import render_latex, render_latex_returning_errors
|
||||
|
@ -12,7 +12,7 @@ import time
|
||||
from typing import Any, Dict, List, NewType, Optional, Sequence, Tuple, Union
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki._legacy import DeprecatedNamesMixin, deprecated, print_deprecation_warning
|
||||
from anki.collection import OpChanges, OpChangesWithId
|
||||
from anki.consts import *
|
||||
|
@ -9,7 +9,7 @@ import copy
|
||||
from typing import Any, List, NewType, Optional, Sequence, Tuple, Union
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki._legacy import DeprecatedNamesMixin
|
||||
from anki.consts import MODEL_STD
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import anki
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
||||
from anki.config import Config
|
||||
|
||||
|
@ -11,7 +11,7 @@ from heapq import *
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki.cards import Card, CardId
|
||||
from anki.consts import *
|
||||
|
@ -14,7 +14,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import List, Literal, Sequence, Tuple
|
||||
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki.cards import Card
|
||||
from anki.collection import OpChanges
|
||||
from anki.consts import *
|
||||
|
@ -6,7 +6,7 @@ from __future__ import annotations
|
||||
from typing import Any, Callable, List, Tuple
|
||||
|
||||
import anki
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki.utils import from_json_bytes
|
||||
|
||||
# pylint: disable=no-member
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
|
||||
# public exports
|
||||
SyncAuth = _pb.SyncAuth
|
||||
|
@ -27,7 +27,7 @@ except ImportError as e:
|
||||
from flask import Response
|
||||
|
||||
from anki import Collection
|
||||
from anki._backend.backend_pb2 import SyncServerMethodRequest
|
||||
from anki.backend_pb2 import SyncServerMethodRequest
|
||||
|
||||
Method = SyncServerMethodRequest.Method # pylint: disable=no-member
|
||||
|
||||
|
@ -16,7 +16,7 @@ import re
|
||||
from typing import Collection, List, Match, Optional, Sequence
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
import anki.collection
|
||||
from anki.collection import OpChanges, OpChangesWithCount
|
||||
from anki.decks import DeckId
|
||||
|
@ -32,7 +32,7 @@ from dataclasses import dataclass
|
||||
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
|
||||
|
||||
import anki
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki.cards import Card
|
||||
from anki.decks import DeckManager
|
||||
|
@ -1,21 +1,21 @@
|
||||
load("@bazel_skylib//lib:paths.bzl", "paths")
|
||||
|
||||
def _py_proto_library_impl(ctx):
|
||||
basename = ctx.file.src.basename
|
||||
outs = [
|
||||
ctx.actions.declare_file(paths.replace_extension(basename, "_pb2.py")),
|
||||
ctx.actions.declare_file(paths.replace_extension(basename, "_pb2.pyi")),
|
||||
]
|
||||
def _py_proto_impl(ctx):
|
||||
outs = []
|
||||
for src in ctx.files.srcs:
|
||||
base = paths.basename(src.path)
|
||||
outs.append(ctx.actions.declare_file(paths.replace_extension(base, "_pb2.py")))
|
||||
outs.append(ctx.actions.declare_file(paths.replace_extension(base, "_pb2.pyi")))
|
||||
|
||||
ctx.actions.run(
|
||||
outputs = outs,
|
||||
inputs = [ctx.file.src],
|
||||
inputs = ctx.files.srcs,
|
||||
executable = ctx.executable.protoc_wrapper,
|
||||
arguments = [
|
||||
ctx.executable.protoc.path,
|
||||
ctx.executable.mypy_protobuf.path,
|
||||
ctx.file.src.path,
|
||||
paths.dirname(outs[0].path),
|
||||
],
|
||||
] + [file.path for file in ctx.files.srcs],
|
||||
tools = [
|
||||
ctx.executable.protoc,
|
||||
ctx.executable.mypy_protobuf,
|
||||
@ -26,10 +26,10 @@ def _py_proto_library_impl(ctx):
|
||||
DefaultInfo(files = depset(direct = outs), data_runfiles = ctx.runfiles(files = outs)),
|
||||
]
|
||||
|
||||
py_proto_library_typed = rule(
|
||||
implementation = _py_proto_library_impl,
|
||||
py_proto = rule(
|
||||
implementation = _py_proto_impl,
|
||||
attrs = {
|
||||
"src": attr.label(allow_single_file = [".proto"]),
|
||||
"srcs": attr.label_list(allow_files = [".proto"]),
|
||||
"protoc_wrapper": attr.label(
|
||||
executable = True,
|
||||
cfg = "exec",
|
||||
|
@ -10,16 +10,9 @@ import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
(protoc, mypy_protobuf, proto, outdir) = sys.argv[1:]
|
||||
(protoc, mypy_protobuf, outdir, *protos) = sys.argv[1:]
|
||||
|
||||
# copy to current dir
|
||||
basename = os.path.basename(proto)
|
||||
shutil.copyfile(proto, basename)
|
||||
|
||||
# output filenames
|
||||
without_ext = os.path.splitext(basename)[0]
|
||||
pb2_py = without_ext + "_pb2.py"
|
||||
pb2_pyi = without_ext + "_pb2.pyi"
|
||||
prefix = "proto/"
|
||||
|
||||
# invoke protoc
|
||||
subprocess.run(
|
||||
@ -28,13 +21,17 @@ subprocess.run(
|
||||
"--plugin=protoc-gen-mypy=" + mypy_protobuf,
|
||||
"--python_out=.",
|
||||
"--mypy_out=.",
|
||||
basename,
|
||||
"-I" + prefix,
|
||||
"-Iexternal/anki/" + prefix,
|
||||
*protos,
|
||||
],
|
||||
# mypy prints to stderr on success :-(
|
||||
stderr=subprocess.DEVNULL,
|
||||
check=True,
|
||||
)
|
||||
|
||||
# move files into output
|
||||
shutil.move(pb2_py, outdir + "/" + pb2_py)
|
||||
shutil.move(pb2_pyi, outdir + "/" + pb2_pyi)
|
||||
for proto in protos:
|
||||
without_prefix_and_ext, _ = os.path.splitext(proto[len(prefix) :])
|
||||
for ext in "_pb2.py", "_pb2.pyi":
|
||||
path = without_prefix_and_ext + ext
|
||||
shutil.move(path, os.path.join(outdir, os.path.basename(path)))
|
||||
|
@ -30,8 +30,8 @@ if subprocess.run(
|
||||
"--",
|
||||
"--config-file",
|
||||
"qt/mypy.ini",
|
||||
"bazel-bin/qt/dmypy.runfiles/net_ankiweb_anki/pylib/anki",
|
||||
"bazel-bin/qt/dmypy.runfiles/net_ankiweb_anki/qt/aqt",
|
||||
"bazel-bin/qt/dmypy.runfiles/anki/pylib/anki",
|
||||
"bazel-bin/qt/dmypy.runfiles/anki/qt/aqt",
|
||||
"--python-executable",
|
||||
os.path.abspath("pip/stubs/extendsitepkgs"),
|
||||
],
|
||||
|
@ -13,7 +13,7 @@ cargo_build_script(
|
||||
name = "build_script",
|
||||
srcs = glob(["build/*.rs"]),
|
||||
build_script_env = {
|
||||
"BACKEND_PROTO": "$(location //proto:backend.proto)",
|
||||
"PROTO_TOP": "$(location //proto:.top_level)",
|
||||
"PROTOC": "$(location @com_google_protobuf//:protoc)",
|
||||
"RSLIB_FTL_ROOT": "$(location @rslib_ftl//:l10n.toml)",
|
||||
"EXTRA_FTL_ROOT": "$(location @extra_ftl//:l10n.toml)",
|
||||
@ -22,9 +22,10 @@ cargo_build_script(
|
||||
crate_root = "build/main.rs",
|
||||
data = [
|
||||
"//ftl",
|
||||
"//proto:backend.proto",
|
||||
"//proto",
|
||||
"@com_google_protobuf//:protoc",
|
||||
# bazel requires us to list these out separately
|
||||
"//proto:.top_level",
|
||||
"@rslib_ftl//:l10n.toml",
|
||||
"@extra_ftl//:l10n.toml",
|
||||
],
|
||||
|
@ -17,7 +17,7 @@ pub trait Service {
|
||||
write!(
|
||||
buf,
|
||||
concat!(" ",
|
||||
"{idx} => {{ let input = {input_type}::decode(input)?;\n",
|
||||
"{idx} => {{ let input = super::{input_type}::decode(input)?;\n",
|
||||
"let output = self.{rust_method}(input)?;\n",
|
||||
"let mut out_bytes = Vec::new(); output.encode(&mut out_bytes)?; Ok(out_bytes) }}, "),
|
||||
idx = idx,
|
||||
@ -38,8 +38,8 @@ pub trait Service {
|
||||
write!(
|
||||
buf,
|
||||
concat!(
|
||||
" fn {method_name}(&self, input: {input_type}) -> ",
|
||||
"Result<{output_type}>;\n"
|
||||
" fn {method_name}(&self, input: super::{input_type}) -> ",
|
||||
"Result<super::{output_type}>;\n"
|
||||
),
|
||||
method_name = method.name,
|
||||
input_type = method.input_type,
|
||||
@ -55,7 +55,6 @@ impl prost_build::ServiceGenerator for CustomGenerator {
|
||||
write!(
|
||||
buf,
|
||||
"pub mod {name}_service {{
|
||||
use super::*;
|
||||
use prost::Message;
|
||||
use crate::error::Result;
|
||||
",
|
||||
@ -73,16 +72,32 @@ fn service_generator() -> Box<dyn prost_build::ServiceGenerator> {
|
||||
|
||||
pub fn write_backend_proto_rs() {
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
let backend_proto;
|
||||
let proto_dir;
|
||||
if let Ok(proto) = env::var("BACKEND_PROTO") {
|
||||
backend_proto = PathBuf::from(proto);
|
||||
proto_dir = backend_proto.parent().unwrap().to_owned();
|
||||
let proto_dir = if let Ok(proto) = env::var("PROTO_TOP") {
|
||||
let backend_proto = PathBuf::from(proto);
|
||||
backend_proto.parent().unwrap().to_owned()
|
||||
} else {
|
||||
backend_proto = PathBuf::from("backend.proto");
|
||||
proto_dir = PathBuf::from("../proto");
|
||||
PathBuf::from("../proto")
|
||||
};
|
||||
|
||||
let subfolders = &["anki"];
|
||||
let mut paths = vec![];
|
||||
|
||||
for subfolder in subfolders {
|
||||
for entry in proto_dir.join(subfolder).read_dir().unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let path = entry.path();
|
||||
if path
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.ends_with(".proto")
|
||||
{
|
||||
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
|
||||
paths.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("cargo:rerun-if-changed={}", backend_proto.to_str().unwrap());
|
||||
|
||||
let mut config = prost_build::Config::new();
|
||||
config
|
||||
@ -92,6 +107,6 @@ pub fn write_backend_proto_rs() {
|
||||
"Deck.Filtered.SearchTerm.Order",
|
||||
"#[derive(strum::EnumIter)]",
|
||||
)
|
||||
.compile_protos(&[&backend_proto], &[&proto_dir, &out_dir])
|
||||
.compile_protos(paths.as_slice(), &[proto_dir, out_dir])
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -1,4 +1,16 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/backend_proto.rs"));
|
||||
pub mod backend {
|
||||
include!(concat!(env!("OUT_DIR"), "/anki.backend.rs"));
|
||||
}
|
||||
pub mod i18n {
|
||||
include!(concat!(env!("OUT_DIR"), "/anki.i18n.rs"));
|
||||
}
|
||||
pub mod generic {
|
||||
include!(concat!(env!("OUT_DIR"), "/anki.generic.rs"));
|
||||
}
|
||||
|
||||
pub use backend::*;
|
||||
pub use generic::*;
|
||||
pub use i18n::*;
|
||||
|
@ -52,7 +52,6 @@ ts_library(
|
||||
deps = [
|
||||
"//ts/components",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"//ts/sveltelib",
|
||||
"@npm//lodash-es",
|
||||
"@npm//svelte",
|
||||
@ -76,7 +75,6 @@ esbuild(
|
||||
"@npm//bootstrap",
|
||||
"@npm//marked",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"//ts/sveltelib",
|
||||
"//ts/components",
|
||||
"//ts/components:svelte_components",
|
||||
@ -123,7 +121,7 @@ jest_test(
|
||||
protobuf = True,
|
||||
deps = [
|
||||
":lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"//ts/lib",
|
||||
"@npm//protobufjs",
|
||||
"@npm//svelte",
|
||||
],
|
||||
|
@ -5,7 +5,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import * as pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import { ChangeNotetypeState, negativeOneToNull, MapContext } from "./lib";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
@ -64,15 +64,15 @@ const exampleInfoSame = {
|
||||
|
||||
function differentState(): ChangeNotetypeState {
|
||||
return new ChangeNotetypeState(
|
||||
pb.BackendProto.NotetypeNames.fromObject(exampleNames),
|
||||
pb.BackendProto.ChangeNotetypeInfo.fromObject(exampleInfoDifferent)
|
||||
Backend.NotetypeNames.fromObject(exampleNames),
|
||||
Backend.ChangeNotetypeInfo.fromObject(exampleInfoDifferent)
|
||||
);
|
||||
}
|
||||
|
||||
function sameState(): ChangeNotetypeState {
|
||||
return new ChangeNotetypeState(
|
||||
pb.BackendProto.NotetypeNames.fromObject(exampleNames),
|
||||
pb.BackendProto.ChangeNotetypeInfo.fromObject(exampleInfoSame)
|
||||
Backend.NotetypeNames.fromObject(exampleNames),
|
||||
Backend.ChangeNotetypeInfo.fromObject(exampleInfoSame)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5,22 +5,20 @@
|
||||
@typescript-eslint/no-non-null-assertion: "off",
|
||||
*/
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import { postRequest } from "lib/postrequest";
|
||||
import { readable, Readable } from "svelte/store";
|
||||
import { isEqual } from "lodash-es";
|
||||
|
||||
export async function getNotetypeNames(): Promise<pb.BackendProto.NotetypeNames> {
|
||||
return pb.BackendProto.NotetypeNames.decode(
|
||||
await postRequest("/_anki/notetypeNames", "")
|
||||
);
|
||||
export async function getNotetypeNames(): Promise<Backend.NotetypeNames> {
|
||||
return Backend.NotetypeNames.decode(await postRequest("/_anki/notetypeNames", ""));
|
||||
}
|
||||
|
||||
export async function getChangeNotetypeInfo(
|
||||
oldNotetypeId: number,
|
||||
newNotetypeId: number
|
||||
): Promise<pb.BackendProto.ChangeNotetypeInfo> {
|
||||
return pb.BackendProto.ChangeNotetypeInfo.decode(
|
||||
): Promise<Backend.ChangeNotetypeInfo> {
|
||||
return Backend.ChangeNotetypeInfo.decode(
|
||||
await postRequest(
|
||||
"/_anki/changeNotetypeInfo",
|
||||
JSON.stringify({ oldNotetypeId, newNotetypeId })
|
||||
@ -29,10 +27,9 @@ export async function getChangeNotetypeInfo(
|
||||
}
|
||||
|
||||
export async function changeNotetype(
|
||||
input: pb.BackendProto.ChangeNotetypeRequest
|
||||
input: Backend.ChangeNotetypeRequest
|
||||
): Promise<void> {
|
||||
const data: Uint8Array =
|
||||
pb.BackendProto.ChangeNotetypeRequest.encode(input).finish();
|
||||
const data: Uint8Array = Backend.ChangeNotetypeRequest.encode(input).finish();
|
||||
await postRequest("/_anki/changeNotetype", data);
|
||||
return;
|
||||
}
|
||||
@ -50,9 +47,9 @@ export function negativeOneToNull(list: number[]): (number | null)[] {
|
||||
export class ChangeNotetypeInfoWrapper {
|
||||
fields: (number | null)[];
|
||||
templates?: (number | null)[];
|
||||
readonly info: pb.BackendProto.ChangeNotetypeInfo;
|
||||
readonly info: Backend.ChangeNotetypeInfo;
|
||||
|
||||
constructor(info: pb.BackendProto.ChangeNotetypeInfo) {
|
||||
constructor(info: Backend.ChangeNotetypeInfo) {
|
||||
this.info = info;
|
||||
const templates = info.input!.newTemplates!;
|
||||
if (templates.length > 0) {
|
||||
@ -114,13 +111,13 @@ export class ChangeNotetypeInfoWrapper {
|
||||
);
|
||||
}
|
||||
|
||||
input(): pb.BackendProto.ChangeNotetypeRequest {
|
||||
return this.info.input as pb.BackendProto.ChangeNotetypeRequest;
|
||||
input(): Backend.ChangeNotetypeRequest {
|
||||
return this.info.input as Backend.ChangeNotetypeRequest;
|
||||
}
|
||||
|
||||
/// Pack changes back into input message for saving.
|
||||
intoInput(): pb.BackendProto.ChangeNotetypeRequest {
|
||||
const input = this.info.input as pb.BackendProto.ChangeNotetypeRequest;
|
||||
intoInput(): Backend.ChangeNotetypeRequest {
|
||||
const input = this.info.input as Backend.ChangeNotetypeRequest;
|
||||
input.newFields = nullToNegativeOne(this.fields);
|
||||
if (this.templates) {
|
||||
input.newTemplates = nullToNegativeOne(this.templates);
|
||||
@ -146,13 +143,10 @@ export class ChangeNotetypeState {
|
||||
|
||||
private info_: ChangeNotetypeInfoWrapper;
|
||||
private infoSetter!: (val: ChangeNotetypeInfoWrapper) => void;
|
||||
private notetypeNames: pb.BackendProto.NotetypeNames;
|
||||
private notetypeNames: Backend.NotetypeNames;
|
||||
private notetypesSetter!: (val: NotetypeListEntry[]) => void;
|
||||
|
||||
constructor(
|
||||
notetypes: pb.BackendProto.NotetypeNames,
|
||||
info: pb.BackendProto.ChangeNotetypeInfo
|
||||
) {
|
||||
constructor(notetypes: Backend.NotetypeNames, info: Backend.ChangeNotetypeInfo) {
|
||||
this.info_ = new ChangeNotetypeInfoWrapper(info);
|
||||
this.info = readable(this.info_, (set) => {
|
||||
this.infoSetter = set;
|
||||
@ -203,7 +197,7 @@ export class ChangeNotetypeState {
|
||||
await changeNotetype(this.dataForSaving());
|
||||
}
|
||||
|
||||
dataForSaving(): pb.BackendProto.ChangeNotetypeRequest {
|
||||
dataForSaving(): Backend.ChangeNotetypeRequest {
|
||||
return this.info_.intoInput();
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ def compile_sass(group, srcs, deps = [], visibility = ["//visibility:private"]):
|
||||
sourcemap = False,
|
||||
deps = deps,
|
||||
visibility = visibility,
|
||||
include_paths = ["external/net_ankiweb_anki"],
|
||||
include_paths = ["external/anki"],
|
||||
)
|
||||
|
||||
native.filegroup(
|
||||
|
@ -17,25 +17,24 @@ filegroup(
|
||||
compile_svelte(
|
||||
name = "svelte",
|
||||
srcs = svelte_files,
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//ts/sass:button_mixins_lib",
|
||||
"//ts/sass/bootstrap",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "components",
|
||||
module_name = "components",
|
||||
srcs = glob(
|
||||
["*.ts"],
|
||||
exclude = ["*.test.ts"],
|
||||
),
|
||||
module_name = "components",
|
||||
tsconfig = "//ts:tsconfig.json",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"//ts/sveltelib",
|
||||
"@npm//@popperjs/core",
|
||||
"@npm//@types/bootstrap",
|
||||
|
@ -35,10 +35,7 @@ ts_library(
|
||||
ts_library(
|
||||
name = "lib",
|
||||
srcs = ["lib.ts"],
|
||||
deps = [
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
],
|
||||
deps = ["//ts/lib"],
|
||||
)
|
||||
|
||||
esbuild(
|
||||
@ -56,7 +53,6 @@ esbuild(
|
||||
":base_css",
|
||||
":index",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"@npm//protobufjs",
|
||||
],
|
||||
)
|
||||
|
@ -3,11 +3,11 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import { buildNextLearnMsg } from "./lib";
|
||||
import { bridgeLink } from "lib/bridgecommand";
|
||||
|
||||
export let info: pb.BackendProto.CongratsInfoResponse;
|
||||
export let info: Backend.CongratsInfoResponse;
|
||||
import * as tr from "lib/i18n";
|
||||
|
||||
const congrats = tr.schedulingCongratulationsFinished();
|
||||
|
@ -1,19 +1,19 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import { postRequest } from "lib/postrequest";
|
||||
import { naturalUnit, unitAmount, unitName } from "lib/time";
|
||||
|
||||
import * as tr from "lib/i18n";
|
||||
|
||||
export async function getCongratsInfo(): Promise<pb.BackendProto.CongratsInfoResponse> {
|
||||
return pb.BackendProto.CongratsInfoResponse.decode(
|
||||
export async function getCongratsInfo(): Promise<Backend.CongratsInfoResponse> {
|
||||
return Backend.CongratsInfoResponse.decode(
|
||||
await postRequest("/_anki/congratsInfo", "")
|
||||
);
|
||||
}
|
||||
|
||||
export function buildNextLearnMsg(info: pb.BackendProto.CongratsInfoResponse): string {
|
||||
export function buildNextLearnMsg(info: Backend.CongratsInfoResponse): string {
|
||||
const secsUntil = info.secsUntilNextLearn;
|
||||
// next learning card not due (/ until tomorrow)?
|
||||
if (secsUntil == 0 || secsUntil > 86_400) {
|
||||
|
@ -68,7 +68,6 @@ ts_library(
|
||||
"//ts:image_module_support",
|
||||
"//ts/components",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"//ts/sveltelib",
|
||||
"@npm//lodash-es",
|
||||
"@npm//svelte",
|
||||
@ -94,7 +93,6 @@ esbuild(
|
||||
"@npm//marked",
|
||||
"@npm//protobufjs",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"//ts/sveltelib",
|
||||
"//ts/components",
|
||||
"//ts/components:svelte_components",
|
||||
@ -141,7 +139,7 @@ jest_test(
|
||||
protobuf = True,
|
||||
deps = [
|
||||
":lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"//ts/lib",
|
||||
"@npm//protobufjs",
|
||||
"@npm//svelte",
|
||||
],
|
||||
|
@ -5,7 +5,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import * as pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import { DeckOptionsState } from "./lib";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
@ -94,7 +94,7 @@ const exampleData = {
|
||||
function startingState(): DeckOptionsState {
|
||||
return new DeckOptionsState(
|
||||
123,
|
||||
pb.BackendProto.DeckConfigsForUpdate.fromObject(exampleData)
|
||||
Backend.DeckConfigsForUpdate.fromObject(exampleData)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
@typescript-eslint/no-non-null-assertion: "off",
|
||||
*/
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import { postRequest } from "lib/postrequest";
|
||||
import { Writable, writable, get, Readable, readable } from "svelte/store";
|
||||
import { isEqual, cloneDeep } from "lodash-es";
|
||||
@ -14,17 +14,16 @@ import type { DynamicSvelteComponent } from "sveltelib/dynamicComponent";
|
||||
|
||||
export async function getDeckOptionsInfo(
|
||||
deckId: number
|
||||
): Promise<pb.BackendProto.DeckConfigsForUpdate> {
|
||||
return pb.BackendProto.DeckConfigsForUpdate.decode(
|
||||
): Promise<Backend.DeckConfigsForUpdate> {
|
||||
return Backend.DeckConfigsForUpdate.decode(
|
||||
await postRequest("/_anki/deckConfigsForUpdate", JSON.stringify({ deckId }))
|
||||
);
|
||||
}
|
||||
|
||||
export async function saveDeckOptions(
|
||||
input: pb.BackendProto.UpdateDeckConfigsRequest
|
||||
input: Backend.UpdateDeckConfigsRequest
|
||||
): Promise<void> {
|
||||
const data: Uint8Array =
|
||||
pb.BackendProto.UpdateDeckConfigsRequest.encode(input).finish();
|
||||
const data: Uint8Array = Backend.UpdateDeckConfigsRequest.encode(input).finish();
|
||||
await postRequest("/_anki/updateDeckConfigs", data);
|
||||
return;
|
||||
}
|
||||
@ -32,7 +31,7 @@ export async function saveDeckOptions(
|
||||
export type DeckOptionsId = number;
|
||||
|
||||
export interface ConfigWithCount {
|
||||
config: pb.BackendProto.DeckConfig;
|
||||
config: Backend.DeckConfig;
|
||||
useCount: number;
|
||||
}
|
||||
|
||||
@ -49,14 +48,14 @@ export interface ConfigListEntry {
|
||||
current: boolean;
|
||||
}
|
||||
|
||||
type ConfigInner = pb.BackendProto.DeckConfig.Config;
|
||||
type ConfigInner = Backend.DeckConfig.Config;
|
||||
export class DeckOptionsState {
|
||||
readonly currentConfig: Writable<ConfigInner>;
|
||||
readonly currentAuxData: Writable<Record<string, unknown>>;
|
||||
readonly configList: Readable<ConfigListEntry[]>;
|
||||
readonly parentLimits: Readable<ParentLimits>;
|
||||
readonly cardStateCustomizer: Writable<string>;
|
||||
readonly currentDeck: pb.BackendProto.DeckConfigsForUpdate.CurrentDeck;
|
||||
readonly currentDeck: Backend.DeckConfigsForUpdate.CurrentDeck;
|
||||
readonly defaults: ConfigInner;
|
||||
readonly addonComponents: Writable<DynamicSvelteComponent[]>;
|
||||
readonly v3Scheduler: boolean;
|
||||
@ -71,13 +70,12 @@ export class DeckOptionsState {
|
||||
private removedConfigs: DeckOptionsId[] = [];
|
||||
private schemaModified: boolean;
|
||||
|
||||
constructor(targetDeckId: number, data: pb.BackendProto.DeckConfigsForUpdate) {
|
||||
constructor(targetDeckId: number, data: Backend.DeckConfigsForUpdate) {
|
||||
this.targetDeckId = targetDeckId;
|
||||
this.currentDeck =
|
||||
data.currentDeck as pb.BackendProto.DeckConfigsForUpdate.CurrentDeck;
|
||||
this.currentDeck = data.currentDeck as Backend.DeckConfigsForUpdate.CurrentDeck;
|
||||
this.defaults = data.defaults!.config! as ConfigInner;
|
||||
this.configs = data.allConfig.map((config) => {
|
||||
const configInner = config.config as pb.BackendProto.DeckConfig;
|
||||
const configInner = config.config as Backend.DeckConfig;
|
||||
return {
|
||||
config: configInner,
|
||||
useCount: config.useCount!,
|
||||
@ -152,12 +150,9 @@ export class DeckOptionsState {
|
||||
}
|
||||
|
||||
/// Clone the current config, making it current.
|
||||
private addConfigFrom(
|
||||
name: string,
|
||||
source: pb.BackendProto.DeckConfig.IConfig
|
||||
): void {
|
||||
private addConfigFrom(name: string, source: Backend.DeckConfig.IConfig): void {
|
||||
const uniqueName = this.ensureNewNameUnique(name);
|
||||
const config = pb.BackendProto.DeckConfig.create({
|
||||
const config = Backend.DeckConfig.create({
|
||||
id: 0,
|
||||
name: uniqueName,
|
||||
config: cloneDeep(source),
|
||||
@ -193,7 +188,7 @@ export class DeckOptionsState {
|
||||
this.updateConfigList();
|
||||
}
|
||||
|
||||
dataForSaving(applyToChildren: boolean): pb.BackendProto.UpdateDeckConfigsRequest {
|
||||
dataForSaving(applyToChildren: boolean): Backend.UpdateDeckConfigsRequest {
|
||||
const modifiedConfigsExcludingCurrent = this.configs
|
||||
.map((c) => c.config)
|
||||
.filter((c, idx) => {
|
||||
@ -207,7 +202,7 @@ export class DeckOptionsState {
|
||||
// current must come last, even if unmodified
|
||||
this.configs[this.selectedIdx].config,
|
||||
];
|
||||
return pb.BackendProto.UpdateDeckConfigsRequest.create({
|
||||
return Backend.UpdateDeckConfigsRequest.create({
|
||||
targetDeckId: this.targetDeckId,
|
||||
removedConfigIds: this.removedConfigs,
|
||||
configs,
|
||||
|
@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
@ -19,9 +19,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { gatherData, buildHistogram } from "./added";
|
||||
import type { GraphData } from "./added";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse | null = null;
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
import * as tr from "lib/i18n";
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
|
||||
let histogramData = null as HistogramData | null;
|
||||
let tableData: TableDatum[] = [];
|
||||
|
@ -45,7 +45,6 @@ ts_library(
|
||||
),
|
||||
deps = [
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"//ts/sveltelib",
|
||||
"@npm//@types/d3",
|
||||
"@npm//@types/lodash",
|
||||
@ -68,7 +67,6 @@ esbuild(
|
||||
deps = [
|
||||
"//ts/sveltelib",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
":index",
|
||||
":base_css",
|
||||
"@npm//protobufjs",
|
||||
|
@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
import InputBox from "./InputBox.svelte";
|
||||
@ -14,7 +14,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { renderButtons } from "./buttons";
|
||||
import { defaultGraphBounds, GraphRange, RevlogRange } from "./graph-helpers";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse | null = null;
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
import * as tr from "lib/i18n";
|
||||
export let revlogRange: RevlogRange;
|
||||
|
||||
|
@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
@ -18,8 +18,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { gatherData, renderCalendar } from "./calendar";
|
||||
import type { GraphData } from "./calendar";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse;
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
export let sourceData: Backend.GraphsResponse;
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
export let revlogRange: RevlogRange;
|
||||
import * as tr from "lib/i18n";
|
||||
export let nightMode: boolean;
|
||||
|
@ -4,7 +4,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
@ -15,9 +15,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { gatherData, renderCards } from "./card-counts";
|
||||
import type { GraphData, TableDatum } from "./card-counts";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse;
|
||||
export let sourceData: Backend.GraphsResponse;
|
||||
import * as tr2 from "lib/i18n";
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
|
||||
let { cardCountsSeparateInactive, browserLinksSupported } = preferences;
|
||||
const dispatch = createEventDispatcher<SearchEventMap>();
|
||||
|
@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import * as tr from "lib/i18n";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
|
||||
@ -17,8 +17,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { gatherData, prepareData } from "./ease";
|
||||
import type { TableDatum, SearchEventMap } from "./graph-helpers";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse | null = null;
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
|
||||
const dispatch = createEventDispatcher<SearchEventMap>();
|
||||
|
||||
|
@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<script lang="typescript">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
import InputBox from "./InputBox.svelte";
|
||||
@ -20,9 +20,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { gatherData, buildHistogram } from "./future-due";
|
||||
import type { GraphData } from "./future-due";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse | null = null;
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
import * as tr from "lib/i18n";
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
|
||||
const dispatch = createEventDispatcher<SearchEventMap>();
|
||||
|
||||
|
@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
import InputBox from "./InputBox.svelte";
|
||||
@ -15,7 +15,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { defaultGraphBounds, RevlogRange, GraphRange } from "./graph-helpers";
|
||||
import { renderHours } from "./hours";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse | null = null;
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
import * as tr from "lib/i18n";
|
||||
export let revlogRange: RevlogRange;
|
||||
let graphRange: GraphRange = GraphRange.Year;
|
||||
|
@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<script lang="typescript">
|
||||
import { timeSpan, MONTH } from "lib/time";
|
||||
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
@ -23,9 +23,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import type { IntervalGraphData } from "./intervals";
|
||||
import type { TableDatum, SearchEventMap } from "./graph-helpers";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse | null = null;
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
import * as tr from "lib/i18n";
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
|
||||
const dispatch = createEventDispatcher<SearchEventMap>();
|
||||
|
||||
|
@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
import InputBox from "./InputBox.svelte";
|
||||
@ -19,7 +19,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { gatherData, renderReviews } from "./reviews";
|
||||
import type { GraphData } from "./reviews";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse | null = null;
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
export let revlogRange: RevlogRange;
|
||||
import * as tr from "lib/i18n";
|
||||
|
||||
|
@ -3,14 +3,14 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
|
||||
import type { TodayData } from "./today";
|
||||
import { gatherData } from "./today";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsResponse | null = null;
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
|
||||
let todayData: TodayData | null = null;
|
||||
$: if (sourceData) {
|
||||
|
@ -6,7 +6,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import type { Writable } from "svelte/store";
|
||||
import type { PreferenceRaw, PreferencePayload } from "sveltelib/preferences";
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import { postRequest } from "lib/postrequest";
|
||||
|
||||
import useAsync from "sveltelib/async";
|
||||
@ -21,24 +21,24 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
async function getGraphData(
|
||||
search: string,
|
||||
days: number
|
||||
): Promise<pb.BackendProto.GraphsResponse> {
|
||||
return pb.BackendProto.GraphsResponse.decode(
|
||||
): Promise<Backend.GraphsResponse> {
|
||||
return Backend.GraphsResponse.decode(
|
||||
await postRequest("/_anki/graphData", JSON.stringify({ search, days }))
|
||||
);
|
||||
}
|
||||
|
||||
async function getGraphPreferences(): Promise<pb.BackendProto.GraphPreferences> {
|
||||
return pb.BackendProto.GraphPreferences.decode(
|
||||
async function getGraphPreferences(): Promise<Backend.GraphPreferences> {
|
||||
return Backend.GraphPreferences.decode(
|
||||
await postRequest("/_anki/graphPreferences", JSON.stringify({}))
|
||||
);
|
||||
}
|
||||
|
||||
async function setGraphPreferences(
|
||||
prefs: PreferencePayload<pb.BackendProto.GraphPreferences>
|
||||
prefs: PreferencePayload<Backend.GraphPreferences>
|
||||
): Promise<void> {
|
||||
await postRequest(
|
||||
"/_anki/setGraphPreferences",
|
||||
pb.BackendProto.GraphPreferences.encode(prefs).finish()
|
||||
Backend.GraphPreferences.encode(prefs).finish()
|
||||
);
|
||||
}
|
||||
|
||||
@ -56,12 +56,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
getPreferences(
|
||||
getGraphPreferences,
|
||||
setGraphPreferences,
|
||||
pb.BackendProto.GraphPreferences.toObject.bind(
|
||||
pb.BackendProto.GraphPreferences
|
||||
) as (
|
||||
preferences: pb.BackendProto.GraphPreferences,
|
||||
Backend.GraphPreferences.toObject.bind(Backend.GraphPreferences) as (
|
||||
preferences: Backend.GraphPreferences,
|
||||
options: { defaults: boolean }
|
||||
) => PreferenceRaw<pb.BackendProto.GraphPreferences>
|
||||
) => PreferenceRaw<Backend.GraphPreferences>
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
|
||||
import {
|
||||
extent,
|
||||
@ -28,8 +28,8 @@ export interface GraphData {
|
||||
daysAdded: number[];
|
||||
}
|
||||
|
||||
export function gatherData(data: pb.BackendProto.GraphsResponse): GraphData {
|
||||
const daysAdded = (data.cards as pb.BackendProto.Card[]).map((card) => {
|
||||
export function gatherData(data: Backend.GraphsResponse): GraphData {
|
||||
const daysAdded = (data.cards as Backend.Card[]).map((card) => {
|
||||
const elapsedSecs = (card.id as number) / 1000 - data.nextDayAtSecs;
|
||||
return Math.ceil(elapsedSecs / 86400);
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
|
||||
import {
|
||||
interpolateRdYlGn,
|
||||
@ -36,18 +36,15 @@ export interface GraphData {
|
||||
mature: ButtonCounts;
|
||||
}
|
||||
|
||||
const ReviewKind = pb.BackendProto.RevlogEntry.ReviewKind;
|
||||
const ReviewKind = Backend.RevlogEntry.ReviewKind;
|
||||
|
||||
export function gatherData(
|
||||
data: pb.BackendProto.GraphsResponse,
|
||||
range: GraphRange
|
||||
): GraphData {
|
||||
export function gatherData(data: Backend.GraphsResponse, range: GraphRange): GraphData {
|
||||
const cutoff = millisecondCutoffForRange(range, data.nextDayAtSecs);
|
||||
const learning: ButtonCounts = [0, 0, 0, 0];
|
||||
const young: ButtonCounts = [0, 0, 0, 0];
|
||||
const mature: ButtonCounts = [0, 0, 0, 0];
|
||||
|
||||
for (const review of data.revlog as pb.BackendProto.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Backend.RevlogEntry[]) {
|
||||
if (cutoff && (review.id as number) < cutoff) {
|
||||
continue;
|
||||
}
|
||||
@ -99,7 +96,7 @@ interface TotalCorrect {
|
||||
export function renderButtons(
|
||||
svgElem: SVGElement,
|
||||
bounds: GraphBounds,
|
||||
origData: pb.BackendProto.GraphsResponse,
|
||||
origData: Backend.GraphsResponse,
|
||||
range: GraphRange
|
||||
): void {
|
||||
const sourceData = gatherData(origData, range);
|
||||
|
@ -5,7 +5,7 @@
|
||||
@typescript-eslint/no-non-null-assertion: "off",
|
||||
*/
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import {
|
||||
interpolateBlues,
|
||||
select,
|
||||
@ -49,16 +49,16 @@ interface DayDatum {
|
||||
date: Date;
|
||||
}
|
||||
|
||||
type WeekdayType = pb.BackendProto.GraphPreferences.Weekday;
|
||||
const Weekday = pb.BackendProto.GraphPreferences.Weekday; /* enum */
|
||||
type WeekdayType = Backend.GraphPreferences.Weekday;
|
||||
const Weekday = Backend.GraphPreferences.Weekday; /* enum */
|
||||
|
||||
export function gatherData(
|
||||
data: pb.BackendProto.GraphsResponse,
|
||||
data: Backend.GraphsResponse,
|
||||
firstDayOfWeek: WeekdayType
|
||||
): GraphData {
|
||||
const reviewCount = new Map<number, number>();
|
||||
|
||||
for (const review of data.revlog as pb.BackendProto.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Backend.RevlogEntry[]) {
|
||||
if (review.buttonChosen == 0) {
|
||||
continue;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import { CardQueue, CardType } from "lib/cards";
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import {
|
||||
schemeGreens,
|
||||
schemeBlues,
|
||||
@ -41,10 +41,7 @@ const barColours = [
|
||||
"grey" /* buried */,
|
||||
];
|
||||
|
||||
function countCards(
|
||||
cards: pb.BackendProto.ICard[],
|
||||
separateInactive: boolean
|
||||
): Count[] {
|
||||
function countCards(cards: Backend.ICard[], separateInactive: boolean): Count[] {
|
||||
let newCards = 0;
|
||||
let learn = 0;
|
||||
let relearn = 0;
|
||||
@ -53,7 +50,7 @@ function countCards(
|
||||
let suspended = 0;
|
||||
let buried = 0;
|
||||
|
||||
for (const card of cards as pb.BackendProto.Card[]) {
|
||||
for (const card of cards as Backend.Card[]) {
|
||||
if (separateInactive) {
|
||||
switch (card.queue) {
|
||||
case CardQueue.Suspended:
|
||||
@ -127,7 +124,7 @@ function countCards(
|
||||
}
|
||||
|
||||
export function gatherData(
|
||||
data: pb.BackendProto.GraphsResponse,
|
||||
data: Backend.GraphsResponse,
|
||||
separateInactive: boolean
|
||||
): GraphData {
|
||||
const totalCards = data.cards.length;
|
||||
|
@ -6,7 +6,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import {
|
||||
extent,
|
||||
histogram,
|
||||
@ -26,8 +26,8 @@ export interface GraphData {
|
||||
eases: number[];
|
||||
}
|
||||
|
||||
export function gatherData(data: pb.BackendProto.GraphsResponse): GraphData {
|
||||
const eases = (data.cards as pb.BackendProto.Card[])
|
||||
export function gatherData(data: Backend.GraphsResponse): GraphData {
|
||||
const eases = (data.cards as Backend.Card[])
|
||||
.filter((c) => [CardType.Review, CardType.Relearn].includes(c.ctype))
|
||||
.map((c) => c.easeFactor / 10);
|
||||
return { eases };
|
||||
|
@ -6,7 +6,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import {
|
||||
extent,
|
||||
histogram,
|
||||
@ -30,13 +30,13 @@ export interface GraphData {
|
||||
haveBacklog: boolean;
|
||||
}
|
||||
|
||||
export function gatherData(data: pb.BackendProto.GraphsResponse): GraphData {
|
||||
const isLearning = (card: pb.BackendProto.Card): boolean =>
|
||||
export function gatherData(data: Backend.GraphsResponse): GraphData {
|
||||
const isLearning = (card: Backend.Card): boolean =>
|
||||
[CardQueue.Learn, CardQueue.PreviewRepeat].includes(card.queue);
|
||||
|
||||
let haveBacklog = false;
|
||||
const due = (data.cards as pb.BackendProto.Card[])
|
||||
.filter((c: pb.BackendProto.Card) => {
|
||||
const due = (data.cards as Backend.Card[])
|
||||
.filter((c: Backend.Card) => {
|
||||
// reviews
|
||||
return (
|
||||
[CardQueue.Review, CardQueue.DayLearn].includes(c.queue) ||
|
||||
@ -44,7 +44,7 @@ export function gatherData(data: pb.BackendProto.GraphsResponse): GraphData {
|
||||
isLearning(c)
|
||||
);
|
||||
})
|
||||
.map((c: pb.BackendProto.Card) => {
|
||||
.map((c: Backend.Card) => {
|
||||
let dueDay: number;
|
||||
|
||||
if (isLearning(c)) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
@typescript-eslint/ban-ts-comment: "off" */
|
||||
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import type { Selection } from "d3";
|
||||
|
||||
// amount of data to fetch from backend
|
||||
@ -28,8 +28,8 @@ export enum GraphRange {
|
||||
}
|
||||
|
||||
export interface GraphsContext {
|
||||
cards: pb.BackendProto.Card[];
|
||||
revlog: pb.BackendProto.RevlogEntry[];
|
||||
cards: Backend.Card[];
|
||||
revlog: Backend.RevlogEntry[];
|
||||
revlogRange: RevlogRange;
|
||||
nightMode: boolean;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import {
|
||||
interpolateBlues,
|
||||
select,
|
||||
@ -37,15 +37,15 @@ interface Hour {
|
||||
correctCount: number;
|
||||
}
|
||||
|
||||
const ReviewKind = pb.BackendProto.RevlogEntry.ReviewKind;
|
||||
const ReviewKind = Backend.RevlogEntry.ReviewKind;
|
||||
|
||||
function gatherData(data: pb.BackendProto.GraphsResponse, range: GraphRange): Hour[] {
|
||||
function gatherData(data: Backend.GraphsResponse, range: GraphRange): Hour[] {
|
||||
const hours = [...Array(24)].map((_n, idx: number) => {
|
||||
return { hour: idx, totalCount: 0, correctCount: 0 } as Hour;
|
||||
});
|
||||
const cutoff = millisecondCutoffForRange(range, data.nextDayAtSecs);
|
||||
|
||||
for (const review of data.revlog as pb.BackendProto.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Backend.RevlogEntry[]) {
|
||||
switch (review.reviewKind) {
|
||||
case ReviewKind.LEARNING:
|
||||
case ReviewKind.REVIEW:
|
||||
@ -74,7 +74,7 @@ function gatherData(data: pb.BackendProto.GraphsResponse, range: GraphRange): Ho
|
||||
export function renderHours(
|
||||
svgElem: SVGElement,
|
||||
bounds: GraphBounds,
|
||||
origData: pb.BackendProto.GraphsResponse,
|
||||
origData: Backend.GraphsResponse,
|
||||
range: GraphRange
|
||||
): void {
|
||||
const data = gatherData(origData, range);
|
||||
|
@ -6,7 +6,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import type pb from "lib/backend_proto";
|
||||
import type { Backend } from "lib/proto";
|
||||
import {
|
||||
extent,
|
||||
histogram,
|
||||
@ -36,10 +36,8 @@ export enum IntervalRange {
|
||||
All = 3,
|
||||
}
|
||||
|
||||
export function gatherIntervalData(
|
||||
data: pb.BackendProto.GraphsResponse
|
||||
): IntervalGraphData {
|
||||
const intervals = (data.cards as pb.BackendProto.Card[])
|
||||
export function gatherIntervalData(data: Backend.GraphsResponse): IntervalGraphData {
|
||||
const intervals = (data.cards as Backend.Card[])
|
||||
.filter((c) => [CardType.Review, CardType.Relearn].includes(c.ctype))
|
||||
.map((c) => c.interval);
|
||||
return { intervals };
|
||||
|
@ -6,7 +6,7 @@
|
||||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
|
||||
import { timeSpan, dayLabel } from "lib/time";
|
||||
import {
|
||||
@ -50,15 +50,15 @@ export interface GraphData {
|
||||
reviewTime: Map<number, Reviews>;
|
||||
}
|
||||
|
||||
const ReviewKind = pb.BackendProto.RevlogEntry.ReviewKind;
|
||||
const ReviewKind = Backend.RevlogEntry.ReviewKind;
|
||||
type BinType = Bin<Map<number, Reviews[]>, number>;
|
||||
|
||||
export function gatherData(data: pb.BackendProto.GraphsResponse): GraphData {
|
||||
export function gatherData(data: Backend.GraphsResponse): GraphData {
|
||||
const reviewCount = new Map<number, Reviews>();
|
||||
const reviewTime = new Map<number, Reviews>();
|
||||
const empty = { mature: 0, young: 0, learn: 0, relearn: 0, early: 0 };
|
||||
|
||||
for (const review of data.revlog as pb.BackendProto.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Backend.RevlogEntry[]) {
|
||||
if (review.reviewKind == ReviewKind.MANUAL) {
|
||||
// don't count days with only manual scheduling
|
||||
continue;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import { studiedToday } from "lib/time";
|
||||
|
||||
import * as tr from "lib/i18n";
|
||||
@ -11,9 +11,9 @@ export interface TodayData {
|
||||
lines: string[];
|
||||
}
|
||||
|
||||
const ReviewKind = pb.BackendProto.RevlogEntry.ReviewKind;
|
||||
const ReviewKind = Backend.RevlogEntry.ReviewKind;
|
||||
|
||||
export function gatherData(data: pb.BackendProto.GraphsResponse): TodayData {
|
||||
export function gatherData(data: Backend.GraphsResponse): TodayData {
|
||||
let answerCount = 0;
|
||||
let answerMillis = 0;
|
||||
let correctCount = 0;
|
||||
@ -26,7 +26,7 @@ export function gatherData(data: pb.BackendProto.GraphsResponse): TodayData {
|
||||
|
||||
const startOfTodayMillis = (data.nextDayAtSecs - 86400) * 1000;
|
||||
|
||||
for (const review of data.revlog as pb.BackendProto.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Backend.RevlogEntry[]) {
|
||||
if (review.id < startOfTodayMillis) {
|
||||
continue;
|
||||
}
|
||||
|
6
ts/lib/proto.ts
Normal file
6
ts/lib/proto.ts
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import { anki } from "./backend_proto";
|
||||
import Backend = anki.backend;
|
||||
export { Backend };
|
@ -8,10 +8,7 @@ load("//ts:compile_sass.bzl", "compile_sass")
|
||||
ts_library(
|
||||
name = "lib",
|
||||
srcs = glob(["*.ts"]),
|
||||
deps = [
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
],
|
||||
deps = ["//ts/lib"],
|
||||
)
|
||||
|
||||
esbuild(
|
||||
@ -25,7 +22,6 @@ esbuild(
|
||||
deps = [
|
||||
":lib",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"@npm//protobufjs",
|
||||
],
|
||||
)
|
||||
|
@ -1,26 +1,26 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import * as pb from "lib/backend_proto";
|
||||
import { Backend } from "lib/proto";
|
||||
import { postRequest } from "lib/postrequest";
|
||||
|
||||
async function getNextStates(): Promise<pb.BackendProto.NextCardStates> {
|
||||
return pb.BackendProto.NextCardStates.decode(
|
||||
async function getNextStates(): Promise<Backend.NextCardStates> {
|
||||
return Backend.NextCardStates.decode(
|
||||
await postRequest("/_anki/nextCardStates", "")
|
||||
);
|
||||
}
|
||||
|
||||
async function setNextStates(
|
||||
key: string,
|
||||
states: pb.BackendProto.NextCardStates
|
||||
states: Backend.NextCardStates
|
||||
): Promise<void> {
|
||||
const data: Uint8Array = pb.BackendProto.NextCardStates.encode(states).finish();
|
||||
const data: Uint8Array = Backend.NextCardStates.encode(states).finish();
|
||||
await postRequest("/_anki/setNextCardStates", data, { key });
|
||||
}
|
||||
|
||||
export async function mutateNextCardStates(
|
||||
key: string,
|
||||
mutator: (states: pb.BackendProto.NextCardStates) => void
|
||||
mutator: (states: Backend.NextCardStates) => void
|
||||
): Promise<void> {
|
||||
const states = await getNextStates();
|
||||
mutator(states);
|
||||
|
@ -91,7 +91,6 @@ def svelte_check(name = "svelte_check", srcs = []):
|
||||
"//ts:tsconfig.json",
|
||||
"//ts/sveltelib",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
"@npm//sass",
|
||||
] + srcs,
|
||||
env = {"SASS_PATH": "$(rootpath //ts:tsconfig.json)/../.."},
|
||||
|
@ -157,9 +157,9 @@ async function writeJs(
|
||||
genDir,
|
||||
// a nasty hack to ensure ts/sass/... resolves correctly
|
||||
// when invoked from an external workspace
|
||||
binDir + "/external/net_ankiweb_anki",
|
||||
genDir + "/external/net_ankiweb_anki",
|
||||
binDir + "/../../../external/net_ankiweb_anki",
|
||||
binDir + "/external/anki",
|
||||
genDir + "/external/anki",
|
||||
binDir + "/../../../external/anki",
|
||||
],
|
||||
},
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user