mirror of
https://github.com/jxpeng98/obsidian-to-NotionNext
synced 2026-07-29 08:08:34 +08:00
feat: add auto sync functionality with configurable delay in settings
This commit is contained in:
@@ -35,6 +35,11 @@ export const en = {
|
||||
NotionUserText: "Enter your notion ID",
|
||||
NotionLinkDisplay: "Notion Link Display",
|
||||
NotionLinkDisplayDesc: "Default is ON, if you want to hide the link in the front matter, please turn it off",
|
||||
AutoSync: "Auto Sync",
|
||||
AutoSyncDesc: "Automatically sync to Notion when frontmatter or content is modified (requires existing NotionID)",
|
||||
AutoSyncDelay: "Auto Sync Delay (seconds)",
|
||||
AutoSyncDelayDesc: "How many seconds to wait after document modification before triggering auto sync (default: 5 seconds, minimum: 2 seconds)",
|
||||
AutoSyncDelayText: "Enter delay in seconds",
|
||||
NotionGeneralSettingHeader: "General Notion Database Settings",
|
||||
NotionGeneralButton: "Notion General Sync",
|
||||
NotionGeneralButtonDesc: "Open this option, Sync to Notion General Database command will be displayed in the command palette (default: ON)",
|
||||
|
||||
@@ -33,6 +33,11 @@ export const ja = {
|
||||
NotionUserText: "Notion IDを入力",
|
||||
NotionLinkDisplay: "Notionリンク表示",
|
||||
NotionLinkDisplayDesc: "デフォルトはONです。front matterにリンクを非表示にしたい場合は、オフにしてください",
|
||||
AutoSync: "自動同期",
|
||||
AutoSyncDesc: "frontmatter またはコンテンツが変更されたときに自動的に Notion に同期します(NotionID が必要)",
|
||||
AutoSyncDelay: "自動同期遅延時間(秒)",
|
||||
AutoSyncDelayDesc: "ドキュメントの変更後、自動同期をトリガーするまでの待機時間(デフォルト:5秒、最小:2秒)",
|
||||
AutoSyncDelayText: "遅延秒数を入力",
|
||||
NotionGeneralSettingHeader: "一般的なNotionデータベース設定",
|
||||
NotionGeneralButton: "一般的なNotion同期",
|
||||
NotionGeneralButtonDesc: "このオプションを開くと、一般的なNotionデータベース同期コマンドがコマンドパレットに表示されます(デフォルト:ON)",
|
||||
|
||||
@@ -35,6 +35,11 @@ export const zh = {
|
||||
NotionUserText: "输入你的 Notion ID",
|
||||
NotionLinkDisplay: "Notion 链接显示",
|
||||
NotionLinkDisplayDesc: "默认开启,如果你不想在front matter中显示链接,请关闭",
|
||||
AutoSync: "自动同步",
|
||||
AutoSyncDesc: "当检测到文档的 frontmatter 或内容发生修改时,自动同步到 Notion(需要文档已有 NotionID)",
|
||||
AutoSyncDelay: "自动同步延迟时间(秒)",
|
||||
AutoSyncDelayDesc: "文档修改后等待多少秒才触发自动同步,避免频繁同步(默认:5秒,最小:2秒)",
|
||||
AutoSyncDelayText: "输入延迟秒数",
|
||||
NotionGeneralSettingHeader: "普通 Notion 数据库设置",
|
||||
NotionGeneralButton: "普通数据库同步",
|
||||
NotionGeneralButtonDesc: "打开此选项,同步到普通数据库命令将显示在命令面板中(默认:开)",
|
||||
|
||||
103
src/main.ts
103
src/main.ts
@@ -1,8 +1,9 @@
|
||||
import { App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting } from "obsidian";
|
||||
import { App, Editor, MarkdownView, Notice, Plugin, PluginSettingTab, Setting, TFile, EventRef } from "obsidian";
|
||||
import { addIcons } from 'src/ui/icon';
|
||||
import { i18nConfig } from "src/lang/I18n";
|
||||
import ribbonCommands from "src/commands/NotionCommands";
|
||||
import { ObsidianSettingTab, PluginSettings, DEFAULT_SETTINGS, DatabaseDetails } from "src/ui/settingTabs";
|
||||
import { uploadCommandNext, uploadCommandGeneral, uploadCommandCustom } from "src/upload/uploadCommand";
|
||||
|
||||
// Remember to rename these classes and interfaces!
|
||||
|
||||
@@ -11,6 +12,9 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
|
||||
settings: PluginSettings;
|
||||
commands: ribbonCommands;
|
||||
app: App;
|
||||
modifyEventRef: EventRef | null = null;
|
||||
autoSyncTimeout: NodeJS.Timeout | null = null;
|
||||
private syncingFiles: Set<string> = new Set();
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
@@ -36,9 +40,18 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
|
||||
// This adds a settings tab so the user can configure various aspects of the plugin
|
||||
this.addSettingTab(new ObsidianSettingTab(this.app, this));
|
||||
|
||||
// Setup auto sync listener
|
||||
this.setupAutoSync();
|
||||
|
||||
}
|
||||
|
||||
onunload() {
|
||||
if (this.modifyEventRef) {
|
||||
this.app.vault.offref(this.modifyEventRef);
|
||||
}
|
||||
if (this.autoSyncTimeout) {
|
||||
clearTimeout(this.autoSyncTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
@@ -80,6 +93,94 @@ export default class ObsidianSyncNotionPlugin extends Plugin {
|
||||
await this.saveSettings();
|
||||
}
|
||||
|
||||
setupAutoSync() {
|
||||
// Remove existing listener if any
|
||||
if (this.modifyEventRef) {
|
||||
this.app.vault.offref(this.modifyEventRef);
|
||||
}
|
||||
|
||||
// Only setup if autoSync is enabled
|
||||
if (!this.settings.autoSync) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen for file modifications
|
||||
this.modifyEventRef = this.app.vault.on('modify', async (file: TFile) => {
|
||||
// Only process markdown files
|
||||
if (!(file instanceof TFile) || file.extension !== 'md') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce: clear existing timeout
|
||||
if (this.autoSyncTimeout) {
|
||||
clearTimeout(this.autoSyncTimeout);
|
||||
}
|
||||
|
||||
// Set a new timeout to trigger sync after user-configured delay (in seconds)
|
||||
const delayMs = (this.settings.autoSyncDelay || 2) * 1000;
|
||||
this.autoSyncTimeout = setTimeout(async () => {
|
||||
await this.autoSyncFile(file);
|
||||
}, delayMs);
|
||||
});
|
||||
}
|
||||
|
||||
async autoSyncFile(file: TFile) {
|
||||
// Check if file is already being synced
|
||||
if (this.syncingFiles.has(file.path)) {
|
||||
console.log(`[AutoSync] File ${file.path} is already being synced, skipping`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.syncingFiles.add(file.path);
|
||||
|
||||
// Get file's frontmatter
|
||||
const frontMatter = this.app.metadataCache.getFileCache(file)?.frontmatter;
|
||||
if (!frontMatter) {
|
||||
console.log(`[AutoSync] No frontmatter found in ${file.path}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find which database this file belongs to by checking for NotionID-{abName}
|
||||
let foundDbDetails: DatabaseDetails | null = null;
|
||||
let notionId: string | null = null;
|
||||
|
||||
for (const key in this.settings.databaseDetails) {
|
||||
const dbDetails = this.settings.databaseDetails[key];
|
||||
const notionIDKey = `NotionID-${dbDetails.abName}`;
|
||||
|
||||
if (frontMatter[notionIDKey]) {
|
||||
foundDbDetails = dbDetails;
|
||||
notionId = String(frontMatter[notionIDKey]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no NotionID found, skip auto sync
|
||||
if (!foundDbDetails || !notionId) {
|
||||
console.log(`[AutoSync] No NotionID found in ${file.path}, skipping auto sync`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[AutoSync] ${new Date().toISOString()} Auto syncing ${file.basename} to ${foundDbDetails.fullName}`);
|
||||
|
||||
// Trigger appropriate upload command based on database format
|
||||
if (foundDbDetails.format === 'next') {
|
||||
await uploadCommandNext(this, this.settings, foundDbDetails, this.app);
|
||||
} else if (foundDbDetails.format === 'general') {
|
||||
await uploadCommandGeneral(this, this.settings, foundDbDetails, this.app);
|
||||
} else if (foundDbDetails.format === 'custom') {
|
||||
await uploadCommandCustom(this, this.settings, foundDbDetails, this.app);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`[AutoSync] Error syncing file ${file.path}:`, error);
|
||||
new Notice(`Auto sync failed for ${file.basename}: ${error.message}`);
|
||||
} finally {
|
||||
this.syncingFiles.delete(file.path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ export interface PluginSettings {
|
||||
bannerUrl: string;
|
||||
notionUser: string;
|
||||
NotionLinkDisplay: boolean;
|
||||
autoSync: boolean;
|
||||
autoSyncDelay: number;
|
||||
proxy: string;
|
||||
GeneralButton: boolean;
|
||||
tagButton: boolean;
|
||||
@@ -49,6 +51,8 @@ export const DEFAULT_SETTINGS: PluginSettings = {
|
||||
bannerUrl: "",
|
||||
notionUser: "",
|
||||
NotionLinkDisplay: true,
|
||||
autoSync: false,
|
||||
autoSyncDelay: 5,
|
||||
proxy: "",
|
||||
GeneralButton: true,
|
||||
tagButton: true,
|
||||
@@ -67,6 +71,7 @@ export const DEFAULT_SETTINGS: PluginSettings = {
|
||||
export class ObsidianSettingTab extends PluginSettingTab {
|
||||
plugin: ObsidianSyncNotionPlugin;
|
||||
databaseEl: HTMLDivElement;
|
||||
autoSyncDelayContainer: HTMLElement | null = null;
|
||||
|
||||
constructor(app: App, plugin: ObsidianSyncNotionPlugin) {
|
||||
super(app, plugin);
|
||||
@@ -87,6 +92,34 @@ export class ObsidianSettingTab extends PluginSettingTab {
|
||||
|
||||
this.createSettingEl(containerEl, i18nConfig.NotionLinkDisplay, i18nConfig.NotionLinkDisplayDesc, 'toggle', i18nConfig.NotionLinkDisplay, this.plugin.settings.NotionLinkDisplay, 'NotionLinkDisplay')
|
||||
|
||||
this.createSettingEl(containerEl, i18nConfig.AutoSync, i18nConfig.AutoSyncDesc, 'toggle', i18nConfig.AutoSync, this.plugin.settings.autoSync, 'autoSync')
|
||||
|
||||
// Auto Sync Delay setting - only visible when autoSync is enabled
|
||||
this.autoSyncDelayContainer = containerEl.createDiv();
|
||||
const delaySetting = new Setting(this.autoSyncDelayContainer)
|
||||
.setName(i18nConfig.AutoSyncDelay)
|
||||
.setDesc(i18nConfig.AutoSyncDelayDesc)
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder(i18nConfig.AutoSyncDelayText)
|
||||
.setValue(String(this.plugin.settings.autoSyncDelay))
|
||||
.onChange(async (value) => {
|
||||
const delay = parseFloat(value);
|
||||
if (!isNaN(delay) && delay >= 2) {
|
||||
this.plugin.settings.autoSyncDelay = delay;
|
||||
await this.plugin.saveSettings();
|
||||
} else if (!isNaN(delay) && delay < 2) {
|
||||
// If user enters less than 2 seconds, set it to 2
|
||||
this.plugin.settings.autoSyncDelay = 2;
|
||||
await this.plugin.saveSettings();
|
||||
text.setValue('2');
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Set initial visibility
|
||||
this.updateAutoSyncDelayVisibility();
|
||||
|
||||
|
||||
// add new button
|
||||
new Setting(containerEl)
|
||||
@@ -151,6 +184,13 @@ export class ObsidianSettingTab extends PluginSettingTab {
|
||||
element.style.alignItems = "center";
|
||||
}
|
||||
|
||||
// Update visibility of autoSyncDelay setting based on autoSync toggle
|
||||
public updateAutoSyncDelayVisibility() {
|
||||
if (this.autoSyncDelayContainer) {
|
||||
this.autoSyncDelayContainer.style.display = this.plugin.settings.autoSync ? "block" : "none";
|
||||
}
|
||||
}
|
||||
|
||||
// function to add one setting element in the setting tab.
|
||||
public createSettingEl(containerEl: HTMLElement, name: string, desc: string, type: string, placeholder: string, holderValue: any, settingsKey: string) {
|
||||
if (type === 'password') {
|
||||
@@ -178,6 +218,12 @@ export class ObsidianSettingTab extends PluginSettingTab {
|
||||
this.plugin.settings[settingsKey] = value; // Update the plugin settings directly
|
||||
await this.plugin.saveSettings();
|
||||
await this.plugin.commands.updateCommand();
|
||||
|
||||
// If autoSync setting changed, update the listener and visibility
|
||||
if (settingsKey === 'autoSync') {
|
||||
this.plugin.setupAutoSync();
|
||||
this.updateAutoSyncDelayVisibility();
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (type === 'text') {
|
||||
|
||||
Reference in New Issue
Block a user