mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 06:52:21 -04:00

* Implement import log screen in Svelte * Show filename in import log screen title * Remove unused NoteRow property * Show number of imported notes * Use a single nid expression * Use 'count' as variable name for consistency * Import from @tslib/backend instead * Fix summary_template typing * Fix clippy warning * Apply suggestions from code review * Fix imports * Contents -> Fields * Increase max length of browser search bar https://github.com/ankitects/anki/pull/2568/files#r1255227035 * Fix race condition in Bootstrap tooltip destruction https://github.com/twbs/bootstrap/issues/37474 * summary_template -> summaryTemplate * Make show link a button * Run import ops on Svelte side * Fix geometry not being restored in CSV Import page * Make VirtualTable fill available height * Keep CSV dialog modal * Reword importing-existing-notes-skipped * Avoid mentioning matching based on first field * Change tick and cross icons * List skipped notes last * Pure CSS spinner * Move set_wants_abort() call to relevant dialogs * Show number of imported cards * Remove bold from first sentence and indent summaries * Update UI after import operations * Add close button to import log page Also make virtual table react to resize event. * Fix typing * Make CSV dialog non-modal again Otherwise user can't interact with browser window. * Update window modality after import * Commit DB and update undo actions after import op * Split frontend proto into separate file, so backend can ignore it Currently the automatically-generated frontend RPC methods get placed in 'backend.js' with all the backend methods; we could optionally split them into a separate 'frontend.js' file in the future. * Migrate import_done from a bridgecmd to a HTTP request * Update plural form of importing-notes-added * Move import response handling to mediasrv * Move task callback to script section * Avoid unnecessary :global() * .log cannot be missing if result exists * Move import log search handling to mediasrv * Type common params of ImportLogDialog * Use else if * Remove console.log() * Add way to test apkg imports in new log screen * Remove unused import * Get actual card count for CSV imports * Use import type * Fix typing error * Ignore import log when checking for changes in Python layer * Apply suggestions from code review * Remove imported card count for now * Avoid non-null assertion in assignment * Change showInBrowser to take an array of notes * Use dataclasses for import log args * Simplify ResultWithChanges in TS * Only abort import when window is modal * Fix ResultWithChanges typing * Fix Rust warnings * Only log one duplicate per incoming note * Update wording about note updates * Remove caveat about found_notes * Reduce font size * Remove redundant map * Give credit to loading.io * Remove unused line --------- Co-authored-by: RumovZ <gp5glkw78@relay.firefox.com>
205 lines
5.3 KiB
Protocol Buffer
205 lines
5.3 KiB
Protocol Buffer
// Copyright: Ankitects Pty Ltd and contributors
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
syntax = "proto3";
|
|
|
|
option java_multiple_files = true;
|
|
|
|
package anki.import_export;
|
|
|
|
import "anki/cards.proto";
|
|
import "anki/collection.proto";
|
|
import "anki/notes.proto";
|
|
import "anki/generic.proto";
|
|
|
|
service ImportExportService {
|
|
rpc ImportAnkiPackage(ImportAnkiPackageRequest) returns (ImportResponse);
|
|
rpc ExportAnkiPackage(ExportAnkiPackageRequest) returns (generic.UInt32);
|
|
rpc GetCsvMetadata(CsvMetadataRequest) returns (CsvMetadata);
|
|
rpc ImportCsv(ImportCsvRequest) returns (ImportResponse);
|
|
rpc ExportNoteCsv(ExportNoteCsvRequest) returns (generic.UInt32);
|
|
rpc ExportCardCsv(ExportCardCsvRequest) returns (generic.UInt32);
|
|
rpc ImportJsonFile(generic.String) returns (ImportResponse);
|
|
rpc ImportJsonString(generic.String) returns (ImportResponse);
|
|
}
|
|
|
|
// Implicitly includes any of the above methods that are not listed in the
|
|
// backend service.
|
|
service BackendImportExportService {
|
|
rpc ImportCollectionPackage(ImportCollectionPackageRequest)
|
|
returns (generic.Empty);
|
|
rpc ExportCollectionPackage(ExportCollectionPackageRequest)
|
|
returns (generic.Empty);
|
|
}
|
|
|
|
message ImportCollectionPackageRequest {
|
|
string col_path = 1;
|
|
string backup_path = 2;
|
|
string media_folder = 3;
|
|
string media_db = 4;
|
|
}
|
|
|
|
message ExportCollectionPackageRequest {
|
|
string out_path = 1;
|
|
bool include_media = 2;
|
|
bool legacy = 3;
|
|
}
|
|
|
|
message ImportAnkiPackageRequest {
|
|
string package_path = 1;
|
|
}
|
|
|
|
message ImportResponse {
|
|
message Note {
|
|
notes.NoteId id = 1;
|
|
repeated string fields = 2;
|
|
}
|
|
message Log {
|
|
repeated Note new = 1;
|
|
repeated Note updated = 2;
|
|
repeated Note duplicate = 3;
|
|
repeated Note conflicting = 4;
|
|
repeated Note first_field_match = 5;
|
|
repeated Note missing_notetype = 6;
|
|
repeated Note missing_deck = 7;
|
|
repeated Note empty_first_field = 8;
|
|
CsvMetadata.DupeResolution dupe_resolution = 9;
|
|
uint32 found_notes = 10;
|
|
}
|
|
collection.OpChanges changes = 1;
|
|
Log log = 2;
|
|
}
|
|
|
|
message ExportAnkiPackageRequest {
|
|
string out_path = 1;
|
|
bool with_scheduling = 2;
|
|
bool with_media = 3;
|
|
bool legacy = 4;
|
|
ExportLimit limit = 5;
|
|
}
|
|
|
|
message PackageMetadata {
|
|
enum Version {
|
|
VERSION_UNKNOWN = 0;
|
|
// When `meta` missing, and collection.anki2 file present.
|
|
VERSION_LEGACY_1 = 1;
|
|
// When `meta` missing, and collection.anki21 file present.
|
|
VERSION_LEGACY_2 = 2;
|
|
// Implies MediaEntry media map, and zstd compression.
|
|
// collection.21b file
|
|
VERSION_LATEST = 3;
|
|
}
|
|
|
|
Version version = 1;
|
|
}
|
|
|
|
message MediaEntries {
|
|
message MediaEntry {
|
|
string name = 1;
|
|
uint32 size = 2;
|
|
bytes sha1 = 3;
|
|
|
|
/// Legacy media maps may include gaps in the media list, so the original
|
|
/// file index is recorded when importing from a HashMap. This field is not
|
|
/// set when exporting.
|
|
optional uint32 legacy_zip_filename = 255;
|
|
}
|
|
|
|
repeated MediaEntry entries = 1;
|
|
}
|
|
|
|
message ImportCsvRequest {
|
|
string path = 1;
|
|
CsvMetadata metadata = 2;
|
|
}
|
|
|
|
message CsvMetadataRequest {
|
|
string path = 1;
|
|
optional CsvMetadata.Delimiter delimiter = 2;
|
|
optional int64 notetype_id = 3;
|
|
optional int64 deck_id = 4;
|
|
optional bool is_html = 5;
|
|
}
|
|
|
|
// Column indices are 1-based to make working with them in TS easier, where
|
|
// unset numerical fields default to 0.
|
|
message CsvMetadata {
|
|
enum DupeResolution {
|
|
UPDATE = 0;
|
|
PRESERVE = 1;
|
|
DUPLICATE = 2;
|
|
// UPDATE_IF_NEWER = 3;
|
|
}
|
|
// Order roughly in ascending expected frequency in note text, because the
|
|
// delimiter detection algorithm is stupidly picking the first one it
|
|
// encounters.
|
|
enum Delimiter {
|
|
TAB = 0;
|
|
PIPE = 1;
|
|
SEMICOLON = 2;
|
|
COLON = 3;
|
|
COMMA = 4;
|
|
SPACE = 5;
|
|
}
|
|
message MappedNotetype {
|
|
int64 id = 1;
|
|
// Source column indices for note fields. One-based. 0 means n/a.
|
|
repeated uint32 field_columns = 2;
|
|
}
|
|
Delimiter delimiter = 1;
|
|
bool is_html = 2;
|
|
repeated string global_tags = 3;
|
|
repeated string updated_tags = 4;
|
|
// Column names as defined by the file or empty strings otherwise. Also used
|
|
// to determine the number of columns.
|
|
repeated string column_labels = 5;
|
|
oneof deck {
|
|
int64 deck_id = 6;
|
|
// One-based. 0 means n/a.
|
|
uint32 deck_column = 7;
|
|
}
|
|
oneof notetype {
|
|
// One notetype for all rows with given column mapping.
|
|
MappedNotetype global_notetype = 8;
|
|
// Row-specific notetypes with automatic mapping by index.
|
|
// One-based. 0 means n/a.
|
|
uint32 notetype_column = 9;
|
|
}
|
|
enum MatchScope {
|
|
NOTETYPE = 0;
|
|
NOTETYPE_AND_DECK = 1;
|
|
}
|
|
// One-based. 0 means n/a.
|
|
uint32 tags_column = 10;
|
|
bool force_delimiter = 11;
|
|
bool force_is_html = 12;
|
|
repeated generic.StringList preview = 13;
|
|
uint32 guid_column = 14;
|
|
DupeResolution dupe_resolution = 15;
|
|
MatchScope match_scope = 16;
|
|
}
|
|
|
|
message ExportCardCsvRequest {
|
|
string out_path = 1;
|
|
bool with_html = 2;
|
|
ExportLimit limit = 3;
|
|
}
|
|
|
|
message ExportNoteCsvRequest {
|
|
string out_path = 1;
|
|
bool with_html = 2;
|
|
bool with_tags = 3;
|
|
bool with_deck = 4;
|
|
bool with_notetype = 5;
|
|
bool with_guid = 6;
|
|
ExportLimit limit = 7;
|
|
}
|
|
|
|
message ExportLimit {
|
|
oneof limit {
|
|
generic.Empty whole_collection = 1;
|
|
int64 deck_id = 2;
|
|
notes.NoteIds note_ids = 3;
|
|
cards.CardIds card_ids = 4;
|
|
}
|
|
}
|