mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
split out remaining tags, stats, media and rendering
This commit is contained in:
parent
35b059ecdb
commit
185e9acd22
44 changed files with 413 additions and 382 deletions
2
defs.bzl
2
defs.bzl
|
@ -3,7 +3,7 @@ load("@bazel_skylib//lib:versions.bzl", "versions")
|
|||
load("@rules_rust//rust:repositories.bzl", "rust_repositories")
|
||||
load("@anki//cargo:crates.bzl", "raze_fetch_remote_crates")
|
||||
load(":python.bzl", "setup_local_python")
|
||||
load(":protobuf.bzl", "setup_protobuf_binary")
|
||||
load("//proto:protobuf.bzl", "setup_protobuf_binary")
|
||||
load("//proto:format.bzl", "setup_clang_format")
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install")
|
||||
load("@io_bazel_rules_sass//:defs.bzl", "sass_repositories")
|
||||
|
|
|
@ -5,15 +5,6 @@ syntax = "proto3";
|
|||
|
||||
package anki.backend;
|
||||
|
||||
import "anki/generic.proto";
|
||||
import "anki/cards.proto";
|
||||
import "anki/collection.proto";
|
||||
import "anki/notes.proto";
|
||||
import "anki/notetypes.proto";
|
||||
|
||||
// Backend methods
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
/// while the protobuf descriptors expose the order services are defined in,
|
||||
/// that information is not available in prost, so we define an enum to make
|
||||
/// sure all clients agree on the service index
|
||||
|
@ -35,54 +26,6 @@ enum ServiceIndex {
|
|||
SERVICE_INDEX_CARDS = 14;
|
||||
}
|
||||
|
||||
service CardRenderingService {
|
||||
rpc ExtractAVTags(ExtractAVTagsRequest) returns (ExtractAVTagsResponse);
|
||||
rpc ExtractLatex(ExtractLatexRequest) returns (ExtractLatexResponse);
|
||||
rpc GetEmptyCards(generic.Empty) returns (EmptyCardsReport);
|
||||
rpc RenderExistingCard(RenderExistingCardRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc RenderUncommittedCard(RenderUncommittedCardRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc RenderUncommittedCardLegacy(RenderUncommittedCardLegacyRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc StripAVTags(generic.String) returns (generic.String);
|
||||
rpc RenderMarkdown(RenderMarkdownRequest) returns (generic.String);
|
||||
}
|
||||
|
||||
service TagsService {
|
||||
rpc ClearUnusedTags(generic.Empty) returns (collection.OpChangesWithCount);
|
||||
rpc AllTags(generic.Empty) returns (generic.StringList);
|
||||
rpc RemoveTags(generic.String) returns (collection.OpChangesWithCount);
|
||||
rpc SetTagCollapsed(SetTagCollapsedRequest) returns (collection.OpChanges);
|
||||
rpc TagTree(generic.Empty) returns (TagTreeNode);
|
||||
rpc ReparentTags(ReparentTagsRequest) returns (collection.OpChangesWithCount);
|
||||
rpc RenameTags(RenameTagsRequest) returns (collection.OpChangesWithCount);
|
||||
rpc AddNoteTags(NoteIdsAndTagsRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
rpc RemoveNoteTags(NoteIdsAndTagsRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
rpc FindAndReplaceTag(FindAndReplaceTagRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
}
|
||||
|
||||
service StatsService {
|
||||
rpc CardStats(cards.CardId) returns (generic.String);
|
||||
rpc Graphs(GraphsRequest) returns (GraphsResponse);
|
||||
rpc GetGraphPreferences(generic.Empty) returns (GraphPreferences);
|
||||
rpc SetGraphPreferences(GraphPreferences) returns (generic.Empty);
|
||||
}
|
||||
|
||||
service MediaService {
|
||||
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);
|
||||
}
|
||||
|
||||
// Backend
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
message BackendInit {
|
||||
repeated string preferred_langs = 1;
|
||||
string locale_folder_path = 2;
|
||||
|
@ -94,9 +37,6 @@ message I18nBackendInit {
|
|||
string locale_folder_path = 5;
|
||||
}
|
||||
|
||||
// Errors
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
message BackendError {
|
||||
enum Kind {
|
||||
INVALID_INPUT = 0;
|
||||
|
@ -121,208 +61,3 @@ message BackendError {
|
|||
// the error subtype
|
||||
Kind kind = 2;
|
||||
}
|
||||
|
||||
// Messages
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
message RenderExistingCardRequest {
|
||||
int64 card_id = 1;
|
||||
bool browser = 2;
|
||||
}
|
||||
|
||||
message RenderUncommittedCardRequest {
|
||||
notes.Note note = 1;
|
||||
uint32 card_ord = 2;
|
||||
notetypes.Notetype.Template template = 3;
|
||||
bool fill_empty = 4;
|
||||
}
|
||||
|
||||
message RenderUncommittedCardLegacyRequest {
|
||||
notes.Note note = 1;
|
||||
uint32 card_ord = 2;
|
||||
bytes template = 3;
|
||||
bool fill_empty = 4;
|
||||
}
|
||||
|
||||
message RenderCardResponse {
|
||||
repeated RenderedTemplateNode question_nodes = 1;
|
||||
repeated RenderedTemplateNode answer_nodes = 2;
|
||||
string css = 3;
|
||||
bool latex_svg = 4;
|
||||
}
|
||||
|
||||
message RenderedTemplateNode {
|
||||
oneof value {
|
||||
string text = 1;
|
||||
RenderedTemplateReplacement replacement = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message RenderedTemplateReplacement {
|
||||
string field_name = 1;
|
||||
string current_text = 2;
|
||||
repeated string filters = 3;
|
||||
}
|
||||
|
||||
message ExtractAVTagsRequest {
|
||||
string text = 1;
|
||||
bool question_side = 2;
|
||||
}
|
||||
|
||||
message ExtractAVTagsResponse {
|
||||
string text = 1;
|
||||
repeated AVTag av_tags = 2;
|
||||
}
|
||||
|
||||
message AVTag {
|
||||
oneof value {
|
||||
string sound_or_video = 1;
|
||||
TTSTag tts = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message TTSTag {
|
||||
string field_text = 1;
|
||||
string lang = 2;
|
||||
repeated string voices = 3;
|
||||
float speed = 4;
|
||||
repeated string other_args = 5;
|
||||
}
|
||||
|
||||
message ExtractLatexRequest {
|
||||
string text = 1;
|
||||
bool svg = 2;
|
||||
bool expand_clozes = 3;
|
||||
}
|
||||
|
||||
message ExtractLatexResponse {
|
||||
string text = 1;
|
||||
repeated ExtractedLatex latex = 2;
|
||||
}
|
||||
|
||||
message ExtractedLatex {
|
||||
string filename = 1;
|
||||
string latex_body = 2;
|
||||
}
|
||||
|
||||
message AddMediaFileRequest {
|
||||
string desired_name = 1;
|
||||
bytes data = 2;
|
||||
}
|
||||
|
||||
message CheckMediaResponse {
|
||||
repeated string unused = 1;
|
||||
repeated string missing = 2;
|
||||
string report = 3;
|
||||
bool have_trash = 4;
|
||||
}
|
||||
|
||||
message TrashMediaFilesRequest {
|
||||
repeated string fnames = 1;
|
||||
}
|
||||
|
||||
message CongratsLearnMessageRequest {
|
||||
float next_due = 1;
|
||||
uint32 remaining = 2;
|
||||
}
|
||||
|
||||
message SetTagCollapsedRequest {
|
||||
string name = 1;
|
||||
bool collapsed = 2;
|
||||
}
|
||||
|
||||
message GetChangedTagsResponse {
|
||||
repeated string tags = 1;
|
||||
}
|
||||
|
||||
message TagTreeNode {
|
||||
string name = 1;
|
||||
repeated TagTreeNode children = 2;
|
||||
uint32 level = 3;
|
||||
bool collapsed = 4;
|
||||
}
|
||||
|
||||
message ReparentTagsRequest {
|
||||
repeated string tags = 1;
|
||||
string new_parent = 2;
|
||||
}
|
||||
|
||||
message RenameTagsRequest {
|
||||
string current_prefix = 1;
|
||||
string new_prefix = 2;
|
||||
}
|
||||
|
||||
message EmptyCardsReport {
|
||||
message NoteWithEmptyCards {
|
||||
int64 note_id = 1;
|
||||
repeated int64 card_ids = 2;
|
||||
bool will_delete_note = 3;
|
||||
}
|
||||
string report = 1;
|
||||
repeated NoteWithEmptyCards notes = 2;
|
||||
}
|
||||
|
||||
message NoteIdsAndTagsRequest {
|
||||
repeated int64 note_ids = 1;
|
||||
string tags = 2;
|
||||
}
|
||||
|
||||
message FindAndReplaceTagRequest {
|
||||
repeated int64 note_ids = 1;
|
||||
string search = 2;
|
||||
string replacement = 3;
|
||||
bool regex = 4;
|
||||
bool match_case = 5;
|
||||
}
|
||||
|
||||
message GraphsRequest {
|
||||
string search = 1;
|
||||
uint32 days = 2;
|
||||
}
|
||||
|
||||
message GraphsResponse {
|
||||
repeated cards.Card cards = 1;
|
||||
repeated RevlogEntry revlog = 2;
|
||||
uint32 days_elapsed = 3;
|
||||
// Based on rollover hour
|
||||
uint32 next_day_at_secs = 4;
|
||||
uint32 scheduler_version = 5;
|
||||
/// Seconds to add to UTC timestamps to get local time.
|
||||
int32 local_offset_secs = 7;
|
||||
}
|
||||
|
||||
message GraphPreferences {
|
||||
enum Weekday {
|
||||
SUNDAY = 0;
|
||||
MONDAY = 1;
|
||||
FRIDAY = 5;
|
||||
SATURDAY = 6;
|
||||
}
|
||||
Weekday calendar_first_day_of_week = 1;
|
||||
bool card_counts_separate_inactive = 2;
|
||||
bool browser_links_supported = 3;
|
||||
bool future_due_show_backlog = 4;
|
||||
}
|
||||
|
||||
message RevlogEntry {
|
||||
enum ReviewKind {
|
||||
LEARNING = 0;
|
||||
REVIEW = 1;
|
||||
RELEARNING = 2;
|
||||
EARLY_REVIEW = 3;
|
||||
MANUAL = 4;
|
||||
}
|
||||
int64 id = 1;
|
||||
int64 cid = 2;
|
||||
int32 usn = 3;
|
||||
uint32 button_chosen = 4;
|
||||
int32 interval = 5;
|
||||
int32 last_interval = 6;
|
||||
uint32 ease_factor = 7;
|
||||
uint32 taken_millis = 8;
|
||||
ReviewKind review_kind = 9;
|
||||
}
|
||||
message RenderMarkdownRequest {
|
||||
string markdown = 1;
|
||||
bool sanitize = 2;
|
||||
}
|
||||
|
|
119
proto/anki/card_rendering.proto
Normal file
119
proto/anki/card_rendering.proto
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.card_rendering;
|
||||
|
||||
import "anki/generic.proto";
|
||||
import "anki/notes.proto";
|
||||
import "anki/notetypes.proto";
|
||||
|
||||
service CardRenderingService {
|
||||
rpc ExtractAVTags(ExtractAVTagsRequest) returns (ExtractAVTagsResponse);
|
||||
rpc ExtractLatex(ExtractLatexRequest) returns (ExtractLatexResponse);
|
||||
rpc GetEmptyCards(generic.Empty) returns (EmptyCardsReport);
|
||||
rpc RenderExistingCard(RenderExistingCardRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc RenderUncommittedCard(RenderUncommittedCardRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc RenderUncommittedCardLegacy(RenderUncommittedCardLegacyRequest)
|
||||
returns (RenderCardResponse);
|
||||
rpc StripAVTags(generic.String) returns (generic.String);
|
||||
rpc RenderMarkdown(RenderMarkdownRequest) returns (generic.String);
|
||||
}
|
||||
|
||||
message ExtractAVTagsRequest {
|
||||
string text = 1;
|
||||
bool question_side = 2;
|
||||
}
|
||||
|
||||
message ExtractAVTagsResponse {
|
||||
string text = 1;
|
||||
repeated AVTag av_tags = 2;
|
||||
}
|
||||
|
||||
message AVTag {
|
||||
oneof value {
|
||||
string sound_or_video = 1;
|
||||
TTSTag tts = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message TTSTag {
|
||||
string field_text = 1;
|
||||
string lang = 2;
|
||||
repeated string voices = 3;
|
||||
float speed = 4;
|
||||
repeated string other_args = 5;
|
||||
}
|
||||
|
||||
message ExtractLatexRequest {
|
||||
string text = 1;
|
||||
bool svg = 2;
|
||||
bool expand_clozes = 3;
|
||||
}
|
||||
|
||||
message ExtractLatexResponse {
|
||||
string text = 1;
|
||||
repeated ExtractedLatex latex = 2;
|
||||
}
|
||||
|
||||
message ExtractedLatex {
|
||||
string filename = 1;
|
||||
string latex_body = 2;
|
||||
}
|
||||
|
||||
message EmptyCardsReport {
|
||||
message NoteWithEmptyCards {
|
||||
int64 note_id = 1;
|
||||
repeated int64 card_ids = 2;
|
||||
bool will_delete_note = 3;
|
||||
}
|
||||
string report = 1;
|
||||
repeated NoteWithEmptyCards notes = 2;
|
||||
}
|
||||
|
||||
message RenderExistingCardRequest {
|
||||
int64 card_id = 1;
|
||||
bool browser = 2;
|
||||
}
|
||||
|
||||
message RenderUncommittedCardRequest {
|
||||
notes.Note note = 1;
|
||||
uint32 card_ord = 2;
|
||||
notetypes.Notetype.Template template = 3;
|
||||
bool fill_empty = 4;
|
||||
}
|
||||
|
||||
message RenderUncommittedCardLegacyRequest {
|
||||
notes.Note note = 1;
|
||||
uint32 card_ord = 2;
|
||||
bytes template = 3;
|
||||
bool fill_empty = 4;
|
||||
}
|
||||
|
||||
message RenderCardResponse {
|
||||
repeated RenderedTemplateNode question_nodes = 1;
|
||||
repeated RenderedTemplateNode answer_nodes = 2;
|
||||
string css = 3;
|
||||
bool latex_svg = 4;
|
||||
}
|
||||
|
||||
message RenderedTemplateNode {
|
||||
oneof value {
|
||||
string text = 1;
|
||||
RenderedTemplateReplacement replacement = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message RenderedTemplateReplacement {
|
||||
string field_name = 1;
|
||||
string current_text = 2;
|
||||
repeated string filters = 3;
|
||||
}
|
||||
|
||||
message RenderMarkdownRequest {
|
||||
string markdown = 1;
|
||||
bool sanitize = 2;
|
||||
}
|
32
proto/anki/media.proto
Normal file
32
proto/anki/media.proto
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.media;
|
||||
|
||||
import "anki/generic.proto";
|
||||
|
||||
service MediaService {
|
||||
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);
|
||||
}
|
||||
|
||||
message CheckMediaResponse {
|
||||
repeated string unused = 1;
|
||||
repeated string missing = 2;
|
||||
string report = 3;
|
||||
bool have_trash = 4;
|
||||
}
|
||||
|
||||
message TrashMediaFilesRequest {
|
||||
repeated string fnames = 1;
|
||||
}
|
||||
|
||||
message AddMediaFileRequest {
|
||||
string desired_name = 1;
|
||||
bytes data = 2;
|
||||
}
|
64
proto/anki/stats.proto
Normal file
64
proto/anki/stats.proto
Normal file
|
@ -0,0 +1,64 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.stats;
|
||||
|
||||
import "anki/generic.proto";
|
||||
import "anki/cards.proto";
|
||||
|
||||
service StatsService {
|
||||
rpc CardStats(cards.CardId) returns (generic.String);
|
||||
rpc Graphs(GraphsRequest) returns (GraphsResponse);
|
||||
rpc GetGraphPreferences(generic.Empty) returns (GraphPreferences);
|
||||
rpc SetGraphPreferences(GraphPreferences) returns (generic.Empty);
|
||||
}
|
||||
|
||||
message GraphsRequest {
|
||||
string search = 1;
|
||||
uint32 days = 2;
|
||||
}
|
||||
|
||||
message GraphsResponse {
|
||||
repeated cards.Card cards = 1;
|
||||
repeated RevlogEntry revlog = 2;
|
||||
uint32 days_elapsed = 3;
|
||||
// Based on rollover hour
|
||||
uint32 next_day_at_secs = 4;
|
||||
uint32 scheduler_version = 5;
|
||||
/// Seconds to add to UTC timestamps to get local time.
|
||||
int32 local_offset_secs = 7;
|
||||
}
|
||||
|
||||
message GraphPreferences {
|
||||
enum Weekday {
|
||||
SUNDAY = 0;
|
||||
MONDAY = 1;
|
||||
FRIDAY = 5;
|
||||
SATURDAY = 6;
|
||||
}
|
||||
Weekday calendar_first_day_of_week = 1;
|
||||
bool card_counts_separate_inactive = 2;
|
||||
bool browser_links_supported = 3;
|
||||
bool future_due_show_backlog = 4;
|
||||
}
|
||||
|
||||
message RevlogEntry {
|
||||
enum ReviewKind {
|
||||
LEARNING = 0;
|
||||
REVIEW = 1;
|
||||
RELEARNING = 2;
|
||||
EARLY_REVIEW = 3;
|
||||
MANUAL = 4;
|
||||
}
|
||||
int64 id = 1;
|
||||
int64 cid = 2;
|
||||
int32 usn = 3;
|
||||
uint32 button_chosen = 4;
|
||||
int32 interval = 5;
|
||||
int32 last_interval = 6;
|
||||
uint32 ease_factor = 7;
|
||||
uint32 taken_millis = 8;
|
||||
ReviewKind review_kind = 9;
|
||||
}
|
60
proto/anki/tags.proto
Normal file
60
proto/anki/tags.proto
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package anki.tags;
|
||||
|
||||
import "anki/generic.proto";
|
||||
import "anki/collection.proto";
|
||||
|
||||
service TagsService {
|
||||
rpc ClearUnusedTags(generic.Empty) returns (collection.OpChangesWithCount);
|
||||
rpc AllTags(generic.Empty) returns (generic.StringList);
|
||||
rpc RemoveTags(generic.String) returns (collection.OpChangesWithCount);
|
||||
rpc SetTagCollapsed(SetTagCollapsedRequest) returns (collection.OpChanges);
|
||||
rpc TagTree(generic.Empty) returns (TagTreeNode);
|
||||
rpc ReparentTags(ReparentTagsRequest) returns (collection.OpChangesWithCount);
|
||||
rpc RenameTags(RenameTagsRequest) returns (collection.OpChangesWithCount);
|
||||
rpc AddNoteTags(NoteIdsAndTagsRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
rpc RemoveNoteTags(NoteIdsAndTagsRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
rpc FindAndReplaceTag(FindAndReplaceTagRequest)
|
||||
returns (collection.OpChangesWithCount);
|
||||
}
|
||||
|
||||
message SetTagCollapsedRequest {
|
||||
string name = 1;
|
||||
bool collapsed = 2;
|
||||
}
|
||||
|
||||
message TagTreeNode {
|
||||
string name = 1;
|
||||
repeated TagTreeNode children = 2;
|
||||
uint32 level = 3;
|
||||
bool collapsed = 4;
|
||||
}
|
||||
|
||||
message ReparentTagsRequest {
|
||||
repeated string tags = 1;
|
||||
string new_parent = 2;
|
||||
}
|
||||
|
||||
message RenameTagsRequest {
|
||||
string current_prefix = 1;
|
||||
string new_prefix = 2;
|
||||
}
|
||||
|
||||
message NoteIdsAndTagsRequest {
|
||||
repeated int64 note_ids = 1;
|
||||
string tags = 2;
|
||||
}
|
||||
|
||||
message FindAndReplaceTagRequest {
|
||||
repeated int64 note_ids = 1;
|
||||
string search = 2;
|
||||
string replacement = 3;
|
||||
bool regex = 4;
|
||||
bool match_case = 5;
|
||||
}
|
|
@ -32,7 +32,7 @@ py_library(
|
|||
"py.typed",
|
||||
":buildinfo",
|
||||
":hooks_gen",
|
||||
":proto",
|
||||
":proto_py",
|
||||
"//pylib/anki/_backend",
|
||||
],
|
||||
imports = [
|
||||
|
@ -110,26 +110,17 @@ filegroup(
|
|||
load("//pylib:protobuf.bzl", "py_proto")
|
||||
|
||||
py_proto(
|
||||
name = "proto_files",
|
||||
name = "proto_py",
|
||||
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"],
|
||||
srcs = [":proto_py", "__init__.py"],
|
||||
imports = [".."],
|
||||
visibility = ["//pylib:__subpackages__"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from anki.buildinfo import version
|
||||
from anki.collection import Collection
|
||||
if not os.getenv("PROTOS_ONLY"):
|
||||
from anki.buildinfo import version
|
||||
from anki.collection import Collection
|
||||
|
||||
if sys.version_info[0] < 3 or sys.version_info[1] < 7:
|
||||
raise Exception("Anki requires Python 3.7+")
|
||||
if sys.version_info[0] < 3 or sys.version_info[1] < 7:
|
||||
raise Exception("Anki requires Python 3.7+")
|
||||
|
||||
# ensure unicode filenames are supported
|
||||
try:
|
||||
"テスト".encode(sys.getfilesystemencoding())
|
||||
except UnicodeEncodeError as exc:
|
||||
raise Exception("Anki requires a UTF-8 locale.") from exc
|
||||
# ensure unicode filenames are supported
|
||||
try:
|
||||
"テスト".encode(sys.getfilesystemencoding())
|
||||
except UnicodeEncodeError as exc:
|
||||
raise Exception("Anki requires a UTF-8 locale.") from exc
|
||||
|
||||
__all__ = ["Collection"]
|
||||
__all__ = ["Collection"]
|
||||
|
|
|
@ -8,6 +8,8 @@ import sys
|
|||
|
||||
import google.protobuf.descriptor
|
||||
|
||||
os.environ["PROTOS_ONLY"] = "1"
|
||||
|
||||
import anki.backend_pb2
|
||||
import anki.i18n_pb2
|
||||
import anki.cards_pb2
|
||||
|
@ -20,6 +22,10 @@ import anki.scheduler_pb2
|
|||
import anki.sync_pb2
|
||||
import anki.configs_pb2
|
||||
import anki.search_pb2
|
||||
import anki.stats_pb2
|
||||
import anki.card_rendering_pb2
|
||||
import anki.tags_pb2
|
||||
import anki.media_pb2
|
||||
|
||||
import stringcase
|
||||
|
||||
|
@ -187,12 +193,16 @@ service_modules = dict(
|
|||
SYNC=anki.sync_pb2,
|
||||
CONFIGS=anki.configs_pb2,
|
||||
SEARCH=anki.search_pb2,
|
||||
STATS=anki.stats_pb2,
|
||||
CARD_RENDERING=anki.card_rendering_pb2,
|
||||
TAGS=anki.tags_pb2,
|
||||
MEDIA=anki.media_pb2,
|
||||
)
|
||||
|
||||
for service in anki.backend_pb2.ServiceIndex.DESCRIPTOR.values:
|
||||
# SERVICE_INDEX_TEST -> _TESTSERVICE
|
||||
base = service.name.replace("SERVICE_INDEX_", "")
|
||||
service_pkg = service_modules.get(base) or anki.backend_pb2
|
||||
service_pkg = service_modules.get(base)
|
||||
service_var = "_" + base.replace("_", "") + "SERVICE"
|
||||
service_obj = getattr(service_pkg, service_var)
|
||||
service_index = service.number
|
||||
|
|
1
pylib/anki/card_rendering_pb2.pyi
Symbolic link
1
pylib/anki/card_rendering_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/card_rendering_pb2.pyi
|
|
@ -7,15 +7,21 @@ from __future__ import annotations
|
|||
|
||||
from typing import Any, Generator, List, Literal, Optional, Sequence, Tuple, Union, cast
|
||||
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import collection_pb2, configs_pb2, generic_pb2, search_pb2
|
||||
from anki import (
|
||||
card_rendering_pb2,
|
||||
collection_pb2,
|
||||
configs_pb2,
|
||||
generic_pb2,
|
||||
search_pb2,
|
||||
stats_pb2,
|
||||
)
|
||||
from anki._legacy import DeprecatedNamesMixin, deprecated
|
||||
|
||||
# protobuf we publicly export - listed first to avoid circular imports
|
||||
SearchNode = search_pb2.SearchNode
|
||||
Progress = collection_pb2.Progress
|
||||
EmptyCardsReport = _pb.EmptyCardsReport
|
||||
GraphPreferences = _pb.GraphPreferences
|
||||
EmptyCardsReport = card_rendering_pb2.EmptyCardsReport
|
||||
GraphPreferences = stats_pb2.GraphPreferences
|
||||
Preferences = configs_pb2.Preferences
|
||||
UndoStatus = collection_pb2.UndoStatus
|
||||
OpChanges = collection_pb2.OpChanges
|
||||
|
|
|
@ -10,8 +10,7 @@ from dataclasses import dataclass
|
|||
from typing import Any, List, Optional, Tuple
|
||||
|
||||
import anki
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki import card_rendering_pb2, hooks
|
||||
from anki.models import NotetypeDict
|
||||
from anki.template import TemplateRenderContext, TemplateRenderOutput
|
||||
from anki.utils import call, isMac, namedtmp, tmpdir
|
||||
|
@ -45,7 +44,9 @@ class ExtractedLatexOutput:
|
|||
latex: List[ExtractedLatex]
|
||||
|
||||
@staticmethod
|
||||
def from_proto(proto: _pb.ExtractLatexResponse) -> ExtractedLatexOutput:
|
||||
def from_proto(
|
||||
proto: card_rendering_pb2.ExtractLatexResponse,
|
||||
) -> ExtractedLatexOutput:
|
||||
return ExtractedLatexOutput(
|
||||
html=proto.text,
|
||||
latex=[
|
||||
|
|
|
@ -10,8 +10,7 @@ import sys
|
|||
import time
|
||||
from typing import Any, Callable, List, Optional, Tuple
|
||||
|
||||
import anki
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import media_pb2
|
||||
from anki._legacy import deprecated
|
||||
from anki.consts import *
|
||||
from anki.latex import render_latex, render_latex_returning_errors
|
||||
|
@ -27,7 +26,7 @@ def media_paths_from_col_path(col_path: str) -> Tuple[str, str]:
|
|||
return (media_folder, media_db)
|
||||
|
||||
|
||||
CheckMediaResponse = _pb.CheckMediaResponse
|
||||
CheckMediaResponse = media_pb2.CheckMediaResponse
|
||||
|
||||
|
||||
# fixme: look into whether we can drop chdir() below
|
||||
|
|
1
pylib/anki/media_pb2.pyi
Symbolic link
1
pylib/anki/media_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/media_pb2.pyi
|
1
pylib/anki/stats_pb2.pyi
Symbolic link
1
pylib/anki/stats_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/stats_pb2.pyi
|
|
@ -16,15 +16,15 @@ import re
|
|||
from typing import Collection, List, Match, Optional, Sequence
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki.backend_pb2 as _pb
|
||||
import anki.collection
|
||||
from anki import tags_pb2
|
||||
from anki.collection import OpChanges, OpChangesWithCount
|
||||
from anki.decks import DeckId
|
||||
from anki.notes import NoteId
|
||||
from anki.utils import ids2str
|
||||
|
||||
# public exports
|
||||
TagTreeNode = _pb.TagTreeNode
|
||||
TagTreeNode = tags_pb2.TagTreeNode
|
||||
MARKED_TAG = "marked"
|
||||
|
||||
|
||||
|
|
1
pylib/anki/tags_pb2.pyi
Symbolic link
1
pylib/anki/tags_pb2.pyi
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../bazel-bin/pylib/anki/tags_pb2.pyi
|
|
@ -32,8 +32,7 @@ from dataclasses import dataclass
|
|||
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
|
||||
|
||||
import anki
|
||||
import anki.backend_pb2 as _pb
|
||||
from anki import hooks
|
||||
from anki import card_rendering_pb2, hooks
|
||||
from anki.cards import Card
|
||||
from anki.decks import DeckManager
|
||||
from anki.errors import TemplateError
|
||||
|
@ -65,7 +64,9 @@ class PartiallyRenderedCard:
|
|||
latex_svg: bool
|
||||
|
||||
@classmethod
|
||||
def from_proto(cls, out: _pb.RenderCardResponse) -> PartiallyRenderedCard:
|
||||
def from_proto(
|
||||
cls, out: card_rendering_pb2.RenderCardResponse
|
||||
) -> PartiallyRenderedCard:
|
||||
qnodes = cls.nodes_from_proto(out.question_nodes)
|
||||
anodes = cls.nodes_from_proto(out.answer_nodes)
|
||||
|
||||
|
@ -73,7 +74,7 @@ class PartiallyRenderedCard:
|
|||
|
||||
@staticmethod
|
||||
def nodes_from_proto(
|
||||
nodes: Sequence[_pb.RenderedTemplateNode],
|
||||
nodes: Sequence[card_rendering_pb2.RenderedTemplateNode],
|
||||
) -> TemplateReplacementList:
|
||||
results: TemplateReplacementList = []
|
||||
for node in nodes:
|
||||
|
@ -90,7 +91,7 @@ class PartiallyRenderedCard:
|
|||
return results
|
||||
|
||||
|
||||
def av_tag_to_native(tag: _pb.AVTag) -> AVTag:
|
||||
def av_tag_to_native(tag: card_rendering_pb2.AVTag) -> AVTag:
|
||||
val = tag.WhichOneof("value")
|
||||
if val == "sound_or_video":
|
||||
return SoundOrVideoTag(filename=tag.sound_or_video)
|
||||
|
@ -104,7 +105,7 @@ def av_tag_to_native(tag: _pb.AVTag) -> AVTag:
|
|||
)
|
||||
|
||||
|
||||
def av_tags_to_native(tags: Sequence[_pb.AVTag]) -> List[AVTag]:
|
||||
def av_tags_to_native(tags: Sequence[card_rendering_pb2.AVTag]) -> List[AVTag]:
|
||||
return list(map(av_tag_to_native, tags))
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@ import sys
|
|||
|
||||
(protoc, mypy_protobuf, outdir, *protos) = sys.argv[1:]
|
||||
|
||||
prefix = "proto/"
|
||||
if protos[0].startswith("external"):
|
||||
prefix = "external/anki/proto/"
|
||||
else:
|
||||
prefix = "proto/"
|
||||
|
||||
# invoke protoc
|
||||
subprocess.run(
|
||||
|
|
|
@ -14,6 +14,7 @@ macro_rules! protobuf {
|
|||
}
|
||||
|
||||
protobuf!(backend);
|
||||
protobuf!(card_rendering);
|
||||
protobuf!(cards);
|
||||
protobuf!(collection);
|
||||
protobuf!(configs);
|
||||
|
@ -21,8 +22,11 @@ protobuf!(deckconfig);
|
|||
protobuf!(decks);
|
||||
protobuf!(generic);
|
||||
protobuf!(i18n);
|
||||
protobuf!(media);
|
||||
protobuf!(notes);
|
||||
protobuf!(notetypes);
|
||||
protobuf!(scheduler);
|
||||
protobuf!(search);
|
||||
protobuf!(stats);
|
||||
protobuf!(sync);
|
||||
protobuf!(tags);
|
||||
|
|
|
@ -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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse | null = null;
|
||||
export let sourceData: Stats.GraphsResponse | null = null;
|
||||
import * as tr from "lib/i18n";
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
export let preferences: PreferenceStore<Stats.GraphPreferences>;
|
||||
|
||||
let histogramData = null as HistogramData | null;
|
||||
let tableData: TableDatum[] = [];
|
||||
|
|
|
@ -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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse | null = null;
|
||||
export let sourceData: Stats.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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse;
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
export let sourceData: Stats.GraphsResponse;
|
||||
export let preferences: PreferenceStore<Stats.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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse;
|
||||
export let sourceData: Stats.GraphsResponse;
|
||||
import * as tr2 from "lib/i18n";
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
export let preferences: PreferenceStore<Stats.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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse | null = null;
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
export let sourceData: Stats.GraphsResponse | null = null;
|
||||
export let preferences: PreferenceStore<Stats.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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse | null = null;
|
||||
export let sourceData: Stats.GraphsResponse | null = null;
|
||||
import * as tr from "lib/i18n";
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
export let preferences: PreferenceStore<Stats.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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse | null = null;
|
||||
export let sourceData: Stats.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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse | null = null;
|
||||
export let sourceData: Stats.GraphsResponse | null = null;
|
||||
import * as tr from "lib/i18n";
|
||||
export let preferences: PreferenceStore<Backend.GraphPreferences>;
|
||||
export let preferences: PreferenceStore<Stats.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 { Backend } from "lib/proto";
|
||||
import type { Stats } 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: Backend.GraphsResponse | null = null;
|
||||
export let sourceData: Stats.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 { Backend } from "lib/proto";
|
||||
import type { Stats } from "lib/proto";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
|
||||
import type { TodayData } from "./today";
|
||||
import { gatherData } from "./today";
|
||||
|
||||
export let sourceData: Backend.GraphsResponse | null = null;
|
||||
export let sourceData: Stats.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 { Backend } from "lib/proto";
|
||||
import { Stats } 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<Backend.GraphsResponse> {
|
||||
return Backend.GraphsResponse.decode(
|
||||
): Promise<Stats.GraphsResponse> {
|
||||
return Stats.GraphsResponse.decode(
|
||||
await postRequest("/_anki/graphData", JSON.stringify({ search, days }))
|
||||
);
|
||||
}
|
||||
|
||||
async function getGraphPreferences(): Promise<Backend.GraphPreferences> {
|
||||
return Backend.GraphPreferences.decode(
|
||||
async function getGraphPreferences(): Promise<Stats.GraphPreferences> {
|
||||
return Stats.GraphPreferences.decode(
|
||||
await postRequest("/_anki/graphPreferences", JSON.stringify({}))
|
||||
);
|
||||
}
|
||||
|
||||
async function setGraphPreferences(
|
||||
prefs: PreferencePayload<Backend.GraphPreferences>
|
||||
prefs: PreferencePayload<Stats.GraphPreferences>
|
||||
): Promise<void> {
|
||||
await postRequest(
|
||||
"/_anki/setGraphPreferences",
|
||||
Backend.GraphPreferences.encode(prefs).finish()
|
||||
Stats.GraphPreferences.encode(prefs).finish()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -56,10 +56,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
getPreferences(
|
||||
getGraphPreferences,
|
||||
setGraphPreferences,
|
||||
Backend.GraphPreferences.toObject.bind(Backend.GraphPreferences) as (
|
||||
preferences: Backend.GraphPreferences,
|
||||
Stats.GraphPreferences.toObject.bind(Stats.GraphPreferences) as (
|
||||
preferences: Stats.GraphPreferences,
|
||||
options: { defaults: boolean }
|
||||
) => PreferenceRaw<Backend.GraphPreferences>
|
||||
) => PreferenceRaw<Stats.GraphPreferences>
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import type { Backend, Cards } from "lib/proto";
|
||||
import type { Stats, Cards } from "lib/proto";
|
||||
|
||||
import {
|
||||
extent,
|
||||
|
@ -28,7 +28,7 @@ export interface GraphData {
|
|||
daysAdded: number[];
|
||||
}
|
||||
|
||||
export function gatherData(data: Backend.GraphsResponse): GraphData {
|
||||
export function gatherData(data: Stats.GraphsResponse): GraphData {
|
||||
const daysAdded = (data.cards as Cards.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 { Backend } from "lib/proto";
|
||||
import { Stats } from "lib/proto";
|
||||
|
||||
import {
|
||||
interpolateRdYlGn,
|
||||
|
@ -36,15 +36,15 @@ export interface GraphData {
|
|||
mature: ButtonCounts;
|
||||
}
|
||||
|
||||
const ReviewKind = Backend.RevlogEntry.ReviewKind;
|
||||
const ReviewKind = Stats.RevlogEntry.ReviewKind;
|
||||
|
||||
export function gatherData(data: Backend.GraphsResponse, range: GraphRange): GraphData {
|
||||
export function gatherData(data: Stats.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 Backend.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Stats.RevlogEntry[]) {
|
||||
if (cutoff && (review.id as number) < cutoff) {
|
||||
continue;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ interface TotalCorrect {
|
|||
export function renderButtons(
|
||||
svgElem: SVGElement,
|
||||
bounds: GraphBounds,
|
||||
origData: Backend.GraphsResponse,
|
||||
origData: Stats.GraphsResponse,
|
||||
range: GraphRange
|
||||
): void {
|
||||
const sourceData = gatherData(origData, range);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
@typescript-eslint/no-non-null-assertion: "off",
|
||||
*/
|
||||
|
||||
import { Backend } from "lib/proto";
|
||||
import { Stats } from "lib/proto";
|
||||
import {
|
||||
interpolateBlues,
|
||||
select,
|
||||
|
@ -49,16 +49,16 @@ interface DayDatum {
|
|||
date: Date;
|
||||
}
|
||||
|
||||
type WeekdayType = Backend.GraphPreferences.Weekday;
|
||||
const Weekday = Backend.GraphPreferences.Weekday; /* enum */
|
||||
type WeekdayType = Stats.GraphPreferences.Weekday;
|
||||
const Weekday = Stats.GraphPreferences.Weekday; /* enum */
|
||||
|
||||
export function gatherData(
|
||||
data: Backend.GraphsResponse,
|
||||
data: Stats.GraphsResponse,
|
||||
firstDayOfWeek: WeekdayType
|
||||
): GraphData {
|
||||
const reviewCount = new Map<number, number>();
|
||||
|
||||
for (const review of data.revlog as Backend.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Stats.RevlogEntry[]) {
|
||||
if (review.buttonChosen == 0) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { CardQueue, CardType } from "lib/cards";
|
||||
import type { Backend, Cards } from "lib/proto";
|
||||
import type { Stats, Cards } from "lib/proto";
|
||||
import {
|
||||
schemeGreens,
|
||||
schemeBlues,
|
||||
|
@ -124,7 +124,7 @@ function countCards(cards: Cards.ICard[], separateInactive: boolean): Count[] {
|
|||
}
|
||||
|
||||
export function gatherData(
|
||||
data: Backend.GraphsResponse,
|
||||
data: Stats.GraphsResponse,
|
||||
separateInactive: boolean
|
||||
): GraphData {
|
||||
const totalCards = data.cards.length;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import type { Backend, Cards } from "lib/proto";
|
||||
import type { Stats, Cards } from "lib/proto";
|
||||
import {
|
||||
extent,
|
||||
histogram,
|
||||
|
@ -26,7 +26,7 @@ export interface GraphData {
|
|||
eases: number[];
|
||||
}
|
||||
|
||||
export function gatherData(data: Backend.GraphsResponse): GraphData {
|
||||
export function gatherData(data: Stats.GraphsResponse): GraphData {
|
||||
const eases = (data.cards as Cards.Card[])
|
||||
.filter((c) => [CardType.Review, CardType.Relearn].includes(c.ctype))
|
||||
.map((c) => c.easeFactor / 10);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import type { Backend, Cards } from "lib/proto";
|
||||
import type { Stats, Cards } from "lib/proto";
|
||||
import {
|
||||
extent,
|
||||
histogram,
|
||||
|
@ -30,7 +30,7 @@ export interface GraphData {
|
|||
haveBacklog: boolean;
|
||||
}
|
||||
|
||||
export function gatherData(data: Backend.GraphsResponse): GraphData {
|
||||
export function gatherData(data: Stats.GraphsResponse): GraphData {
|
||||
const isLearning = (card: Cards.Card): boolean =>
|
||||
[CardQueue.Learn, CardQueue.PreviewRepeat].includes(card.queue);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@typescript-eslint/no-explicit-any: "off",
|
||||
@typescript-eslint/ban-ts-comment: "off" */
|
||||
|
||||
import type { Backend, Cards } from "lib/proto";
|
||||
import type { Stats, Cards } from "lib/proto";
|
||||
import type { Selection } from "d3";
|
||||
|
||||
// amount of data to fetch from backend
|
||||
|
@ -29,7 +29,7 @@ export enum GraphRange {
|
|||
|
||||
export interface GraphsContext {
|
||||
cards: Cards.Card[];
|
||||
revlog: Backend.RevlogEntry[];
|
||||
revlog: Stats.RevlogEntry[];
|
||||
revlogRange: RevlogRange;
|
||||
nightMode: boolean;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import { Backend } from "lib/proto";
|
||||
import { Stats } from "lib/proto";
|
||||
import {
|
||||
interpolateBlues,
|
||||
select,
|
||||
|
@ -37,15 +37,15 @@ interface Hour {
|
|||
correctCount: number;
|
||||
}
|
||||
|
||||
const ReviewKind = Backend.RevlogEntry.ReviewKind;
|
||||
const ReviewKind = Stats.RevlogEntry.ReviewKind;
|
||||
|
||||
function gatherData(data: Backend.GraphsResponse, range: GraphRange): Hour[] {
|
||||
function gatherData(data: Stats.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 Backend.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Stats.RevlogEntry[]) {
|
||||
switch (review.reviewKind) {
|
||||
case ReviewKind.LEARNING:
|
||||
case ReviewKind.REVIEW:
|
||||
|
@ -74,7 +74,7 @@ function gatherData(data: Backend.GraphsResponse, range: GraphRange): Hour[] {
|
|||
export function renderHours(
|
||||
svgElem: SVGElement,
|
||||
bounds: GraphBounds,
|
||||
origData: Backend.GraphsResponse,
|
||||
origData: Stats.GraphsResponse,
|
||||
range: GraphRange
|
||||
): void {
|
||||
const data = gatherData(origData, range);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import type { Backend, Cards } from "lib/proto";
|
||||
import type { Stats, Cards } from "lib/proto";
|
||||
import {
|
||||
extent,
|
||||
histogram,
|
||||
|
@ -36,7 +36,7 @@ export enum IntervalRange {
|
|||
All = 3,
|
||||
}
|
||||
|
||||
export function gatherIntervalData(data: Backend.GraphsResponse): IntervalGraphData {
|
||||
export function gatherIntervalData(data: Stats.GraphsResponse): IntervalGraphData {
|
||||
const intervals = (data.cards as Cards.Card[])
|
||||
.filter((c) => [CardType.Review, CardType.Relearn].includes(c.ctype))
|
||||
.map((c) => c.interval);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
@typescript-eslint/no-explicit-any: "off",
|
||||
*/
|
||||
|
||||
import { Backend } from "lib/proto";
|
||||
import { Stats } from "lib/proto";
|
||||
|
||||
import { timeSpan, dayLabel } from "lib/time";
|
||||
import {
|
||||
|
@ -50,15 +50,15 @@ export interface GraphData {
|
|||
reviewTime: Map<number, Reviews>;
|
||||
}
|
||||
|
||||
const ReviewKind = Backend.RevlogEntry.ReviewKind;
|
||||
const ReviewKind = Stats.RevlogEntry.ReviewKind;
|
||||
type BinType = Bin<Map<number, Reviews[]>, number>;
|
||||
|
||||
export function gatherData(data: Backend.GraphsResponse): GraphData {
|
||||
export function gatherData(data: Stats.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 Backend.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Stats.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 { Backend } from "lib/proto";
|
||||
import { Stats } 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 = Backend.RevlogEntry.ReviewKind;
|
||||
const ReviewKind = Stats.RevlogEntry.ReviewKind;
|
||||
|
||||
export function gatherData(data: Backend.GraphsResponse): TodayData {
|
||||
export function gatherData(data: Stats.GraphsResponse): TodayData {
|
||||
let answerCount = 0;
|
||||
let answerMillis = 0;
|
||||
let correctCount = 0;
|
||||
|
@ -26,7 +26,7 @@ export function gatherData(data: Backend.GraphsResponse): TodayData {
|
|||
|
||||
const startOfTodayMillis = (data.nextDayAtSecs - 86400) * 1000;
|
||||
|
||||
for (const review of data.revlog as Backend.RevlogEntry[]) {
|
||||
for (const review of data.revlog as Stats.RevlogEntry[]) {
|
||||
if (review.id < startOfTodayMillis) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import { anki } from "./backend_proto";
|
||||
import Backend = anki.backend;
|
||||
import Cards = anki.cards;
|
||||
import DeckConfig = anki.deckconfig;
|
||||
import Notetypes = anki.notetypes;
|
||||
import Scheduler = anki.scheduler;
|
||||
export { Backend, Cards, DeckConfig, Notetypes, Scheduler };
|
||||
import Stats = anki.stats;
|
||||
export { Stats, Cards, DeckConfig, Notetypes, Scheduler };
|
||||
|
|
Loading…
Reference in a new issue