mirror of
https://github.com/long2icc/sonicnote-sync.git
synced 2026-07-22 07:45:14 +00:00
feat: 更新版本至1.1.0,新增包含转录内容选项,优化同步逻辑
This commit is contained in:
parent
9a018c4494
commit
e45cbe6cc7
10 changed files with 53 additions and 28 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "sonicnote-sync",
|
||||
"name": "SonicNote Sync",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Sync recordings from SonicNote to Obsidian as Markdown files",
|
||||
"author": "EasyLinkIn",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "sonicnote-sync",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "Sync recordings from SonicNote to Obsidian as Markdown files",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -133,10 +133,10 @@
|
|||
<body>
|
||||
|
||||
<header class="header">
|
||||
<div class="version">v1.0.0</div>
|
||||
<div class="version">v1.1.0</div>
|
||||
<h1>SonicNote Sync</h1>
|
||||
<p>将 SonicNote 妙记的录音、转录、总结同步到 Obsidian,以 Markdown 文件管理。</p>
|
||||
<a class="download-btn" href="sonicnote-sync.zip" download>
|
||||
<a class="download-btn" href="sonicnote-sync-v1.1.0.zip" download>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||
下载插件
|
||||
</a>
|
||||
|
|
@ -144,6 +144,18 @@
|
|||
|
||||
<div class="container">
|
||||
|
||||
<div class="card">
|
||||
<h2>更新记录</h2>
|
||||
<h3>v1.1.0</h3>
|
||||
<ul>
|
||||
<li>修复录音进行中重复创建文件的问题</li>
|
||||
<li>AI 总结移至转录内容之前,优先阅读</li>
|
||||
<li>新增"包含转录内容"开关,可按需关闭</li>
|
||||
<li>文件名去除日期前缀,直接使用录音原始名称</li>
|
||||
<li>切换为 HTTPS 接口</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>前置要求</h2>
|
||||
<ul>
|
||||
|
|
@ -155,7 +167,7 @@
|
|||
<div class="card">
|
||||
<h2>安装</h2>
|
||||
<ol>
|
||||
<li>点击上方按钮下载 <span class="inline-code">sonicnote-sync.zip</span></li>
|
||||
<li>点击上方按钮下载 <span class="inline-code">sonicnote-sync-v1.1.0.zip</span></li>
|
||||
<li>解压 zip 文件,得到以下文件:
|
||||
<ul style="margin-top:4px;">
|
||||
<li><span class="inline-code">main.js</span></li>
|
||||
|
|
@ -204,8 +216,8 @@
|
|||
<tbody>
|
||||
<tr><td>Frontmatter</td><td>录音元数据(ID、时间、时长、设备名、标签等)</td></tr>
|
||||
<tr><td>笔记</td><td>你在 App 中手写的笔记内容</td></tr>
|
||||
<tr><td>转录内容</td><td>AI 转写文本(含说话人、时间戳)</td></tr>
|
||||
<tr><td>AI 总结</td><td>智能总结内容(要点、行动项等)</td></tr>
|
||||
<tr><td>转录内容</td><td>AI 转写文本(含说话人、时间戳,可在设置中关闭)</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -216,6 +228,7 @@
|
|||
<thead><tr><th>设置</th><th>默认值</th><th>说明</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>同步文件夹</td><td><span class="inline-code">SonicNoteSync</span></td><td>Markdown 文件存放目录</td></tr>
|
||||
<tr><td>包含转录内容</td><td>开启</td><td>关闭后同步文件中不包含逐字转录</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
BIN
release/sonicnote-sync-v1.1.0.zip
Normal file
BIN
release/sonicnote-sync-v1.1.0.zip
Normal file
Binary file not shown.
Binary file not shown.
|
|
@ -11,10 +11,7 @@ export function sanitizeFileName(name: string): string {
|
|||
|
||||
export function formatFileName(recording: Recording): string {
|
||||
const displayName = recording.recordNickName || recording.recordName || '未命名录音';
|
||||
const date = recording.recordTime
|
||||
? recording.recordTime.substring(0, 10)
|
||||
: new Date().toISOString().substring(0, 10);
|
||||
return `${date}-${sanitizeFileName(displayName)}`;
|
||||
return sanitizeFileName(displayName);
|
||||
}
|
||||
|
||||
function formatDuration(seconds: string | number): string {
|
||||
|
|
@ -96,6 +93,14 @@ export function toMarkdown(
|
|||
parts.push('');
|
||||
}
|
||||
|
||||
// Summary section (before transcript)
|
||||
if (summary && summary.summaryContent) {
|
||||
parts.push('## AI 总结');
|
||||
parts.push('');
|
||||
parts.push(summary.summaryContent.trim());
|
||||
parts.push('');
|
||||
}
|
||||
|
||||
// Transcript section
|
||||
if (transcript && transcript.length > 0) {
|
||||
parts.push('## 转录内容');
|
||||
|
|
@ -104,13 +109,5 @@ export function toMarkdown(
|
|||
parts.push('');
|
||||
}
|
||||
|
||||
// Summary section
|
||||
if (summary && summary.summaryContent) {
|
||||
parts.push('## AI 总结');
|
||||
parts.push('');
|
||||
parts.push(summary.summaryContent.trim());
|
||||
parts.push('');
|
||||
}
|
||||
|
||||
return parts.join('\n');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,17 @@ export class SonicNoteSettingTab extends PluginSettingTab {
|
|||
await this.saveSettings();
|
||||
}));
|
||||
|
||||
// Include transcript
|
||||
new Setting(containerEl)
|
||||
.setName('包含转录内容')
|
||||
.setDesc('关闭后同步的文件中不包含逐字转录内容')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(settings.includeTranscript)
|
||||
.onChange(async (value) => {
|
||||
settings.includeTranscript = value;
|
||||
await this.saveSettings();
|
||||
}));
|
||||
|
||||
// Login status & actions
|
||||
const loginSection = containerEl.createDiv();
|
||||
loginSection.createEl('h3', { text: '账号' });
|
||||
|
|
|
|||
19
src/sync.ts
19
src/sync.ts
|
|
@ -116,20 +116,20 @@ export class SyncService {
|
|||
private async processRecording(recording: Recording, localIndex: Map<string, LocalFileInfo>, settings: SonicNotePluginSettings): Promise<void> {
|
||||
const syncTime = new Date().toISOString();
|
||||
|
||||
// Check if we need to update
|
||||
const local = localIndex.get(recording.audioId);
|
||||
if (local && local.syncTime && recording.updateTime) {
|
||||
if (recording.updateTime <= local.syncTime) {
|
||||
// No update needed
|
||||
|
||||
// Found existing file for this audioId — update it
|
||||
if (local && local.path) {
|
||||
// Skip if no update needed (has updateTime and it's older than syncTime)
|
||||
if (local.syncTime && recording.updateTime && recording.updateTime <= local.syncTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for conflict (user edited file locally after sync)
|
||||
const file = this.app.vault.getAbstractFileByPath(local.path);
|
||||
if (file instanceof TFile) {
|
||||
// Check for conflict (user edited file locally after sync)
|
||||
const fileMtime = new Date(file.stat.mtime).toISOString();
|
||||
if (fileMtime > local.syncTime) {
|
||||
// Conflict — write to a new file instead
|
||||
if (local.syncTime && fileMtime > local.syncTime) {
|
||||
await this.writeRecordingToNewFile(recording, syncTime, settings, local.path);
|
||||
return;
|
||||
}
|
||||
|
|
@ -172,11 +172,12 @@ export class SyncService {
|
|||
}
|
||||
|
||||
private async buildRecordingContent(recording: Recording, syncTime: string): Promise<string> {
|
||||
const settings = this.getSettings();
|
||||
const tasks: [string, Promise<TranscriptSegment[] | SummaryData | string | null>][] = [];
|
||||
|
||||
// Fetch transcript if available (status 2 = completed)
|
||||
// Fetch transcript if enabled and available (status 2 = completed)
|
||||
let transcript: TranscriptSegment[] | null = null;
|
||||
if (recording.transcriptStatus === 2) {
|
||||
if (settings.includeTranscript && recording.transcriptStatus === 2) {
|
||||
tasks.push(['transcript', this.api.fetchTranscriptResult(recording.audioId).catch(() => null)]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ export interface SonicNotePluginSettings {
|
|||
serverUrl: string;
|
||||
syncFolder: string;
|
||||
pageSize: number;
|
||||
includeTranscript: boolean;
|
||||
token: string;
|
||||
phoneNumber: string;
|
||||
lastSyncTime: string;
|
||||
|
|
@ -13,6 +14,7 @@ export const DEFAULT_SETTINGS: SonicNotePluginSettings = {
|
|||
serverUrl: 'https://ainote.easylinkin.com:18048/prod-api',
|
||||
syncFolder: 'SonicNoteSync',
|
||||
pageSize: 50,
|
||||
includeTranscript: true,
|
||||
token: '',
|
||||
phoneNumber: '',
|
||||
lastSyncTime: '',
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
"1.0.0": "0.15.0"
|
||||
"1.0.0": "0.15.0",
|
||||
"1.1.0": "0.15.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue