mirror of
https://github.com/fancive/obsidian-parallel-reader.git
synced 2026-07-22 06:53:43 +00:00
feat: add folder-level batch summarization command
Register parallel-reader-batch-generate command. It prompts the user for a folder path via a Modal, finds all .md files in that folder (non-recursive), skips files whose cache is still valid, and runs runForFile() sequentially on the rest, showing per-file progress notices. Add i18n keys for the new UI strings in both zh and en. https://claude.ai/code/session_016QvEfqw6YZ3RjwBHrJ4w8S
This commit is contained in:
parent
10d811f197
commit
02fc5678ae
2 changed files with 69 additions and 1 deletions
58
main.ts
58
main.ts
|
|
@ -1,5 +1,5 @@
|
|||
'use strict';
|
||||
import { MarkdownView, Notice, Plugin, requestUrl, TFile } from 'obsidian';
|
||||
import { MarkdownView, Modal, Notice, Plugin, requestUrl, TFile } from 'obsidian';
|
||||
import { findLineForAnchor } from './src/anchor';
|
||||
import { serializeCacheFile, shouldConfirmRegenerate, touchCacheEntry } from './src/cache';
|
||||
import { CacheManager } from './src/cache-manager';
|
||||
|
|
@ -208,6 +208,11 @@ class ParallelReaderPlugin extends Plugin {
|
|||
name: this.t('cmdCardJump'),
|
||||
callback: () => this.jumpActiveCard(),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-batch-generate',
|
||||
name: this.t('cmdBatchGenerate'),
|
||||
callback: () => this.runBatchForFolder(),
|
||||
});
|
||||
|
||||
this.addSettingTab(new ParallelReaderSettingTab(this.app, this));
|
||||
|
||||
|
|
@ -551,6 +556,57 @@ class ParallelReaderPlugin extends Plugin {
|
|||
});
|
||||
}
|
||||
|
||||
async runBatchForFolder() {
|
||||
const plugin = this;
|
||||
const folderPath = await new Promise<string | null>((resolve) => {
|
||||
class FolderPromptModal extends Modal {
|
||||
private input!: HTMLInputElement;
|
||||
onOpen() {
|
||||
this.contentEl.createEl('p', { text: plugin.t('batchSelectFolder') });
|
||||
this.input = this.contentEl.createEl('input', { type: 'text' });
|
||||
this.input.placeholder = plugin.t('batchFolderPrompt');
|
||||
this.input.style.width = '100%';
|
||||
this.input.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
resolve(this.input.value.trim());
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
this.contentEl.createEl('button', { text: 'OK' }).addEventListener('click', () => {
|
||||
resolve(this.input.value.trim());
|
||||
this.close();
|
||||
});
|
||||
}
|
||||
onClose() {
|
||||
resolve(null);
|
||||
}
|
||||
}
|
||||
new FolderPromptModal(plugin.app).open();
|
||||
});
|
||||
if (folderPath === null) return;
|
||||
const allFiles = this.app.vault.getMarkdownFiles().filter((f) => {
|
||||
if (folderPath === '') return !f.path.includes('/');
|
||||
return f.parent?.path === folderPath;
|
||||
});
|
||||
if (allFiles.length === 0) {
|
||||
new Notice(this.t('batchNoMarkdown'));
|
||||
return;
|
||||
}
|
||||
let skipped = 0;
|
||||
for (let i = 0; i < allFiles.length; i++) {
|
||||
const file = allFiles[i];
|
||||
new Notice(this.t('batchProgress', { current: i + 1, total: allFiles.length }));
|
||||
const content = await this.app.vault.read(file);
|
||||
const entry = this.cacheManager.get(file.path);
|
||||
if (entry && cacheEntryMatches(entry, content, this.settings)) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
await this.runForFile(file, false);
|
||||
}
|
||||
new Notice(this.t('batchDone', { total: allFiles.length, skipped }));
|
||||
}
|
||||
|
||||
resolveCardAnchors(content: string, rawCards: RawCard[]) {
|
||||
const resolved: ResolvedCard[] = (rawCards || []).map((c: RawCard) => ({
|
||||
title: c.title,
|
||||
|
|
|
|||
12
src/i18n.ts
12
src/i18n.ts
|
|
@ -145,6 +145,12 @@ export const STRINGS: Record<string, Record<string, string>> = {
|
|||
clearAllCacheButton: '清除所有缓存',
|
||||
settingStreamingName: '流式输出',
|
||||
settingStreamingDesc: '启用后生成时实时显示 LLM 输出进度(仅 OpenAI Chat 和 Anthropic 格式支持)',
|
||||
cmdBatchGenerate: '批量生成对照笔记(当前文件夹)',
|
||||
batchSelectFolder: '请输入要批量处理的文件夹路径(留空为 Vault 根目录)',
|
||||
batchFolderPrompt: '文件夹路径',
|
||||
batchNoMarkdown: '该文件夹下没有 Markdown 文件',
|
||||
batchProgress: '批量生成:{current}/{total}',
|
||||
batchDone: '批量生成完成:共处理 {total} 篇,跳过缓存 {skipped} 篇',
|
||||
},
|
||||
en: {
|
||||
appTitle: 'Parallel Reader',
|
||||
|
|
@ -295,6 +301,12 @@ export const STRINGS: Record<string, Record<string, string>> = {
|
|||
settingStreamingName: 'Streaming output',
|
||||
settingStreamingDesc:
|
||||
'Show real-time LLM output progress during generation (OpenAI Chat and Anthropic formats only)',
|
||||
cmdBatchGenerate: 'Batch generate parallel notes (current folder)',
|
||||
batchSelectFolder: 'Enter the folder path to batch-process (leave blank for Vault root)',
|
||||
batchFolderPrompt: 'Folder path',
|
||||
batchNoMarkdown: 'No Markdown files found in that folder',
|
||||
batchProgress: 'Batch generating: {current}/{total}',
|
||||
batchDone: 'Batch complete: processed {total}, skipped {skipped} (cached)',
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue