mirror of
https://github.com/panatgithub/AnkiHeadingSync.git
synced 2026-07-22 06:51:43 +00:00
- Support for QA Group and normal cards migration. - Preservation of noteId and learning history. - 自动同步过程中的 Anki 笔记类型迁移 - 支持问答组和普通卡片的迁移 - 保留笔记 ID 和学习历史记录
135 lines
No EOL
4.8 KiB
TypeScript
135 lines
No EOL
4.8 KiB
TypeScript
import { Notice } from "obsidian";
|
|
|
|
import { renderPluginFileFailuresInline } from "@/application/errors/PluginUserError";
|
|
import type { ClearCurrentFileSyncedCardsResult, CleanupEmptyDecksResult } from "@/application/use-cases/cleanupResetTypes";
|
|
import type { ManualSyncResult } from "@/application/use-cases/manualSyncTypes";
|
|
import type { DeckResolutionWarning } from "@/domain/manual-sync/value-objects/DeckResolution";
|
|
import { formatList, resolvePluginLocale, t, type TranslationKey } from "@/presentation/i18n";
|
|
|
|
export class NoticeService {
|
|
info(message: string): void {
|
|
new Notice(message, 5000);
|
|
}
|
|
|
|
error(message: string): void {
|
|
new Notice(message, 8000);
|
|
}
|
|
|
|
showSyncSummary(kind: "currentFile" | "vault", result: ManualSyncResult): void {
|
|
const locale = resolvePluginLocale();
|
|
const summaryKey = kind === "currentFile" ? "notice.summary.currentFileSync" : "notice.summary.vaultSync";
|
|
const summary = t(summaryKey, {
|
|
scannedFiles: result.scannedFiles,
|
|
scannedCards: result.scannedCards,
|
|
created: result.created,
|
|
updated: result.updated,
|
|
migratedNoteTypes: result.migratedNoteTypes,
|
|
migratedDecks: result.migratedDecks,
|
|
orphaned: result.orphaned,
|
|
uploadedMedia: result.uploadedMedia,
|
|
skippedUnchangedCards: result.skippedUnchangedCards,
|
|
});
|
|
|
|
const segments = [summary];
|
|
if (result.markerWriteConflictFiles.length > 0) {
|
|
segments.push(t("notice.summary.markerWriteConflicts", {
|
|
files: formatList(locale, result.markerWriteConflictFiles),
|
|
}));
|
|
}
|
|
if (result.warnings.length > 0) {
|
|
segments.push(t("notice.summary.warningsCount", { count: result.warnings.length }));
|
|
}
|
|
|
|
this.info(segments.join(" "));
|
|
for (const warning of result.warnings.slice(0, 3)) {
|
|
this.info(this.renderDeckWarning(warning));
|
|
}
|
|
}
|
|
|
|
showRebuildSummary(result: ManualSyncResult): void {
|
|
const locale = resolvePluginLocale();
|
|
const segments = [t("notice.summary.rebuild", {
|
|
scannedFiles: result.scannedFiles,
|
|
scannedCards: result.scannedCards,
|
|
migratedDecks: result.migratedDecks,
|
|
orphaned: result.orphaned,
|
|
rewrittenMarkers: result.rewrittenMarkers,
|
|
skippedUnchangedCards: result.skippedUnchangedCards,
|
|
})];
|
|
|
|
if (result.markerWriteConflictFiles.length > 0) {
|
|
segments.push(t("notice.summary.markerWriteConflicts", {
|
|
files: formatList(locale, result.markerWriteConflictFiles),
|
|
}));
|
|
}
|
|
if (result.warnings.length > 0) {
|
|
segments.push(t("notice.summary.warningsCount", { count: result.warnings.length }));
|
|
}
|
|
|
|
this.info(segments.join(" "));
|
|
for (const warning of result.warnings.slice(0, 3)) {
|
|
this.info(this.renderDeckWarning(warning));
|
|
}
|
|
}
|
|
|
|
showClearCurrentFileSummary(result: ClearCurrentFileSyncedCardsResult): void {
|
|
const locale = resolvePluginLocale();
|
|
const segments = [t("notice.summary.clearCurrentFile", {
|
|
trackedCards: result.trackedCards,
|
|
trackedGroups: result.trackedGroups,
|
|
deletedNotes: result.deletedNotes,
|
|
removedMarkers: result.removedMarkers,
|
|
removedCardMarkers: result.removedCardMarkers,
|
|
removedGroupMarkers: result.removedGroupMarkers,
|
|
deletedLocalRecords: result.deletedLocalRecords,
|
|
})];
|
|
|
|
if (result.conflictFiles.length > 0) {
|
|
segments.push(t("notice.summary.markerRemovalConflicts", {
|
|
files: formatList(locale, result.conflictFiles),
|
|
}));
|
|
}
|
|
if (result.failureFiles.length > 0) {
|
|
segments.push(t("notice.summary.failures", {
|
|
items: renderPluginFileFailuresInline(result.failureFiles),
|
|
}));
|
|
}
|
|
|
|
this.info(segments.join(" "));
|
|
}
|
|
|
|
showCleanupEmptyDecksSummary(result: CleanupEmptyDecksResult): void {
|
|
const locale = resolvePluginLocale();
|
|
const segments = [t("notice.summary.cleanupEmptyDecks", {
|
|
candidateCount: result.candidateCount,
|
|
selectedCount: result.selectedCount,
|
|
deletedCount: result.deletedCount,
|
|
skippedCount: result.skippedDeckNames.length,
|
|
})];
|
|
|
|
if (result.skippedDeckNames.length > 0) {
|
|
segments.push(t("notice.summary.skippedDecks", {
|
|
decks: formatList(locale, result.skippedDeckNames),
|
|
}));
|
|
}
|
|
|
|
this.info(segments.join(" "));
|
|
}
|
|
|
|
private renderDeckWarning(warning: DeckResolutionWarning): string {
|
|
return t(getDeckWarningMessageKey(warning.code), warning.params);
|
|
}
|
|
}
|
|
|
|
function getDeckWarningMessageKey(code: DeckResolutionWarning["code"]): TranslationKey {
|
|
switch (code) {
|
|
case "deck_conflict_yaml_body":
|
|
return "warnings.deck.conflictYamlBody";
|
|
case "deck_multiple_body_declarations":
|
|
return "warnings.deck.multipleBodyDeclarations";
|
|
case "deck_invalid_folder_segment":
|
|
return "warnings.deck.invalidFolderSegment";
|
|
case "deck_fallback_default":
|
|
return "warnings.deck.fallbackDefault";
|
|
}
|
|
} |