parent
95c423e231
commit
558fbd0d09
|
|
@ -18,7 +18,7 @@
|
|||
<caption label="&zotero.__addonRef__.export.option.label;"></caption>
|
||||
<rows flex="1">
|
||||
<row>
|
||||
<checkbox id="__addonRef__-export-embedLink" checked="true" />
|
||||
<checkbox id="__addonRef__-export-embedLink" checked="true" oncommand="Zotero.Knowledge4Zotero.export.doUpdate(event)" />
|
||||
<label value="&zotero.__addonRef__.export.link.enable.label;" />
|
||||
</row>
|
||||
<row>
|
||||
|
|
@ -31,13 +31,17 @@
|
|||
<caption label="&zotero.__addonRef__.export.markdown.label;"></caption>
|
||||
<rows flex="1">
|
||||
<row>
|
||||
<checkbox id="__addonRef__-export-enablefile" checked="true" oncommand="Zotero.Knowledge4Zotero.export.doUpdate(event)" />
|
||||
<checkbox id="__addonRef__-export-enablefile" checked="true" oncommand="Zotero.Knowledge4Zotero.export.doUpdate(event)" />
|
||||
<label value="&zotero.__addonRef__.export.file.enable.label;" />
|
||||
</row>
|
||||
<row>
|
||||
<checkbox id="__addonRef__-export-enablesingle" checked="false" oncommand="Zotero.Knowledge4Zotero.export.doUpdate(event)" />
|
||||
<label value="&zotero.__addonRef__.export.singlefile.enable.label;" />
|
||||
</row>
|
||||
<row>
|
||||
<checkbox id="__addonRef__-export-enableautosync" checked="false" oncommand="Zotero.Knowledge4Zotero.export.doUpdate(event)" />
|
||||
<label value="&zotero.__addonRef__.export.enableautosync.enable.label;" />
|
||||
</row>
|
||||
</rows>
|
||||
</groupbox>
|
||||
<groupbox flex="1">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/overlay.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/overlay.css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % ZoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
%ZoteroDTD;
|
||||
<!ENTITY % knowledgeDTD SYSTEM "chrome://__addonRef__/locale/overlay.dtd">
|
||||
%knowledgeDTD;
|
||||
]>
|
||||
|
||||
<dialog id="betternotes-sync-dialog" windowtype="betternotes-sync" title="&zotero.__addonRef__.sync.title;" orient="vertical" width="300" height="300" buttons="cancel,accept,help" ondialogaccept="Zotero.Knowledge4Zotero.sync.doAccept();" ondialoghelp="Zotero.Knowledge4Zotero.sync.doExport();" onload="Zotero.Knowledge4Zotero.sync.doLoad(window);" onunload="Zotero.Knowledge4Zotero.sync.doUnload();" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml" style="padding:2em" persist="screenX screenY width height" buttonlabelhelp="&zotero.__addonRef__.sync.export.label;">
|
||||
<script src="chrome://zotero/content/include.js" />
|
||||
<vbox flex="1">
|
||||
<label value="&zotero.__addonRef__.sync.path.label;" />
|
||||
<label id="__addonRef__-sync-path" />
|
||||
<label value="&zotero.__addonRef__.sync.lastsync.label;" />
|
||||
<label id="__addonRef__-sync-lastsync" />
|
||||
<hbox>
|
||||
<checkbox id="__addonRef__-sync-enable" label="&zotero.__addonRef__.sync.enable.label;" checked="true" />
|
||||
<button flex="0" label="&zotero.__addonRef__.sync.dosync.label;" oncommand="Zotero.Knowledge4Zotero.sync.doSync(true)"></button>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</dialog>
|
||||
|
|
@ -30,11 +30,19 @@
|
|||
<!ENTITY zotero.__addonRef__.export.markdown.label "MarkDown Settings">
|
||||
<!ENTITY zotero.__addonRef__.export.file.enable.label "Export to MarkDown File">
|
||||
<!ENTITY zotero.__addonRef__.export.singlefile.enable.label "Export Linked Notes to MarkDown File">
|
||||
<!ENTITY zotero.__addonRef__.export.enableautosync.enable.label "Auto Sync to Export Path">
|
||||
<!ENTITY zotero.__addonRef__.export.richtext.label "RichText(MS Word) Settings">
|
||||
<!ENTITY zotero.__addonRef__.export.copy.enable.label "Export to clipboard">
|
||||
<!ENTITY zotero.__addonRef__.export.pdf.label "PDF Settings">
|
||||
<!ENTITY zotero.__addonRef__.export.pdf.enable.label "Export to PDF">
|
||||
|
||||
<!ENTITY zotero.__addonRef__.sync.title "Sync Status">
|
||||
<!ENTITY zotero.__addonRef__.sync.export.label "Export to...">
|
||||
<!ENTITY zotero.__addonRef__.sync.path.label "Sync to:">
|
||||
<!ENTITY zotero.__addonRef__.sync.lastsync.label "Last sync:">
|
||||
<!ENTITY zotero.__addonRef__.sync.enable.label "Keep in sync">
|
||||
<!ENTITY zotero.__addonRef__.sync.dosync.label "Sync Now">
|
||||
|
||||
<!ENTITY zotero.__addonRef__.wizard.title "Welcomed to Zotero Better Notes">
|
||||
<!ENTITY zotero.__addonRef__.wizard.page1.header "Zotero Better Notes User Guide">
|
||||
<!ENTITY zotero.__addonRef__.wizard.page1.description "Click Next to Continue.">
|
||||
|
|
|
|||
|
|
@ -30,11 +30,19 @@
|
|||
<!ENTITY zotero.__addonRef__.export.markdown.label "MarkDown设置">
|
||||
<!ENTITY zotero.__addonRef__.export.file.enable.label "导出为MarkDown文件">
|
||||
<!ENTITY zotero.__addonRef__.export.singlefile.enable.label "导出链接的子笔记为MarkDown文件">
|
||||
<!ENTITY zotero.__addonRef__.export.enableautosync.enable.label "修改时自动同步到导出路径">
|
||||
<!ENTITY zotero.__addonRef__.export.richtext.label "富文本(MS Word)设置">
|
||||
<!ENTITY zotero.__addonRef__.export.copy.enable.label "导出到剪贴板">
|
||||
<!ENTITY zotero.__addonRef__.export.pdf.label "PDF设置">
|
||||
<!ENTITY zotero.__addonRef__.export.pdf.enable.label "导出到PDF">
|
||||
|
||||
<!ENTITY zotero.__addonRef__.sync.title "同步状态">
|
||||
<!ENTITY zotero.__addonRef__.sync.export.label "导出为...">
|
||||
<!ENTITY zotero.__addonRef__.sync.path.label "同步到:">
|
||||
<!ENTITY zotero.__addonRef__.sync.lastsync.label "最近同步:">
|
||||
<!ENTITY zotero.__addonRef__.sync.enable.label "保持同步">
|
||||
<!ENTITY zotero.__addonRef__.sync.dosync.label "立刻同步">
|
||||
|
||||
<!ENTITY zotero.__addonRef__.wizard.title "欢迎使用 Zotero Better Notes">
|
||||
<!ENTITY zotero.__addonRef__.wizard.page1.header "Zotero Better Notes 用户指引">
|
||||
<!ENTITY zotero.__addonRef__.wizard.page1.description "单击下一步以继续。">
|
||||
|
|
|
|||
|
|
@ -1734,8 +1734,13 @@ let bundle;
|
|||
Zotero.debug(newAbsPath);
|
||||
let newFile = oldFile;
|
||||
try {
|
||||
newFile = _Zotero.File.copyToUnique(oldFile, newAbsPath).path;
|
||||
newFile = newFile.replace(/\\/g, "/");
|
||||
// Don't overwrite
|
||||
if (await OS.File.exists(newAbsPath)) {
|
||||
newFile = newAbsPath.replace(/\\/g, "/");
|
||||
} else {
|
||||
newFile = _Zotero.File.copyToUnique(oldFile, newAbsPath).path;
|
||||
newFile = newFile.replace(/\\/g, "/");
|
||||
}
|
||||
newFile = `attachments/${newFile.split(/\//).pop()}`;
|
||||
} catch (e) {
|
||||
Zotero.debug(e);
|
||||
|
|
|
|||
|
|
@ -4,12 +4,14 @@ import AddonWizard from "./wizard";
|
|||
import AddonExport from "./export";
|
||||
import Knowledge from "./knowledge";
|
||||
import AddonTemplate from "./template";
|
||||
import AddonSync from "./sync";
|
||||
|
||||
class Knowledge4Zotero {
|
||||
public events: AddonEvents;
|
||||
public views: AddonViews;
|
||||
public wizard: AddonWizard;
|
||||
public export: AddonExport;
|
||||
public sync: AddonSync;
|
||||
public template: AddonTemplate;
|
||||
public knowledge: Knowledge;
|
||||
|
||||
|
|
@ -18,6 +20,7 @@ class Knowledge4Zotero {
|
|||
this.views = new AddonViews(this);
|
||||
this.wizard = new AddonWizard(this);
|
||||
this.export = new AddonExport(this);
|
||||
this.sync = new AddonSync(this);
|
||||
this.template = new AddonTemplate(this);
|
||||
this.knowledge = new Knowledge(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@ class AddonEvents extends AddonBase {
|
|||
Zotero.debug("Knowledge4Zotero: main knowledge modify check.");
|
||||
this._Addon.views.updateOutline();
|
||||
}
|
||||
// Check Note Sync
|
||||
const syncIds = this._Addon.sync.getSyncNoteIds();
|
||||
if (ids.filter((id) => syncIds.includes(id)).length > 0) {
|
||||
this._Addon.sync.setSync();
|
||||
Zotero.debug("Better Notes: sync planned.");
|
||||
}
|
||||
}
|
||||
if (
|
||||
(event == "select" &&
|
||||
|
|
@ -118,6 +124,9 @@ class AddonEvents extends AddonBase {
|
|||
this._Addon.views.switchKey(true);
|
||||
|
||||
this.initItemSelectListener();
|
||||
|
||||
// Set a init sync
|
||||
this._Addon.sync.setSync();
|
||||
}
|
||||
|
||||
private async initWorkspaceTab() {
|
||||
|
|
@ -1292,6 +1301,25 @@ class AddonEvents extends AddonBase {
|
|||
if (!item) {
|
||||
item = this._Addon.knowledge.getWorkspaceNote();
|
||||
}
|
||||
// If this note is in sync list, open sync window
|
||||
if (this._Addon.sync.getSyncNoteIds().includes(item.id)) {
|
||||
const io = {
|
||||
dataIn: item,
|
||||
dataOut: {} as any,
|
||||
deferred: Zotero.Promise.defer(),
|
||||
};
|
||||
|
||||
(window as unknown as XULWindow).openDialog(
|
||||
"chrome://Knowledge4Zotero/content/sync.xul",
|
||||
"",
|
||||
"chrome,centerscreen,width=500,height=200",
|
||||
io
|
||||
);
|
||||
await io.deferred.promise;
|
||||
if (!io.dataOut.export) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const io = {
|
||||
dataIn: null,
|
||||
dataOut: null,
|
||||
|
|
@ -1301,14 +1329,18 @@ class AddonEvents extends AddonBase {
|
|||
(window as unknown as XULWindow).openDialog(
|
||||
"chrome://Knowledge4Zotero/content/export.xul",
|
||||
"",
|
||||
"chrome,centerscreen,width=300,height=450",
|
||||
"chrome,centerscreen,width=400,height=400",
|
||||
io
|
||||
);
|
||||
await io.deferred.promise;
|
||||
|
||||
const options = io.dataOut;
|
||||
if (options.exportFile && options.exportSingleFile) {
|
||||
await this._Addon.knowledge.exportNotesToFile([item], false);
|
||||
await this._Addon.knowledge.exportNotesToFile(
|
||||
[item],
|
||||
false,
|
||||
options.exportAutoSync
|
||||
);
|
||||
} else {
|
||||
await this._Addon.knowledge.exportNoteToFile(
|
||||
item,
|
||||
|
|
@ -1545,6 +1577,8 @@ class AddonEvents extends AddonBase {
|
|||
this._Addon.template.resetTemplates();
|
||||
// Initialize citation style
|
||||
this._Addon.template.getCitationStyle();
|
||||
// Initialize sync notes
|
||||
this._Addon.sync.getSyncNoteIds();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,14 @@ class AddonExport extends AddonBase {
|
|||
) as XUL.Checkbox
|
||||
).checked = exportSingleFile;
|
||||
}
|
||||
let exportAutoSync = Zotero.Prefs.get("Knowledge4Zotero.exportAutoSync");
|
||||
if (typeof exportAutoSync !== "undefined") {
|
||||
(
|
||||
this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-enableautosync"
|
||||
) as XUL.Checkbox
|
||||
).checked = exportAutoSync;
|
||||
}
|
||||
let embedLink = Zotero.Prefs.get("Knowledge4Zotero.embedLink");
|
||||
if (typeof embedLink !== "undefined") {
|
||||
(
|
||||
|
|
@ -67,26 +75,49 @@ class AddonExport extends AddonBase {
|
|||
}
|
||||
this.doUpdate();
|
||||
}
|
||||
doUpdate() {
|
||||
(
|
||||
this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-embedLink"
|
||||
) as XUL.Checkbox
|
||||
).disabled = (
|
||||
this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-enablesingle"
|
||||
) as XUL.Checkbox
|
||||
).checked;
|
||||
doUpdate(event: XULEvent = undefined) {
|
||||
let embedLink = this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-embedLink"
|
||||
) as XUL.Checkbox;
|
||||
|
||||
(
|
||||
this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-enablesingle"
|
||||
) as XUL.Checkbox
|
||||
).disabled = !(
|
||||
this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-enablefile"
|
||||
) as XUL.Checkbox
|
||||
).checked;
|
||||
let exportFile = this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-enablefile"
|
||||
) as XUL.Checkbox;
|
||||
let exportSingleFile = this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-enablesingle"
|
||||
) as XUL.Checkbox;
|
||||
let exportAutoSync = this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-enableautosync"
|
||||
) as XUL.Checkbox;
|
||||
|
||||
if (event) {
|
||||
if (
|
||||
event.target.id === "Knowledge4Zotero-export-embedLink" &&
|
||||
embedLink.checked
|
||||
) {
|
||||
exportSingleFile.checked = false;
|
||||
exportAutoSync.checked = false;
|
||||
}
|
||||
if (event.target.id === "Knowledge4Zotero-export-enablesingle") {
|
||||
if (exportSingleFile.checked) {
|
||||
embedLink.checked = false;
|
||||
} else {
|
||||
exportAutoSync.checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exportFile.checked && !embedLink.checked) {
|
||||
exportSingleFile.disabled = false;
|
||||
} else {
|
||||
exportSingleFile.disabled = true;
|
||||
}
|
||||
|
||||
if (exportFile.checked && exportSingleFile.checked) {
|
||||
exportAutoSync.disabled = false;
|
||||
} else {
|
||||
exportAutoSync.disabled = true;
|
||||
}
|
||||
}
|
||||
doUnload() {
|
||||
this.io.deferred && this.io.deferred.resolve();
|
||||
|
|
@ -103,6 +134,11 @@ class AddonExport extends AddonBase {
|
|||
"Knowledge4Zotero-export-enablesingle"
|
||||
) as XUL.Checkbox
|
||||
).checked;
|
||||
let exportAutoSync = (
|
||||
this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-enableautosync"
|
||||
) as XUL.Checkbox
|
||||
).checked;
|
||||
let embedLink = (
|
||||
this._window.document.getElementById(
|
||||
"Knowledge4Zotero-export-embedLink"
|
||||
|
|
@ -125,6 +161,7 @@ class AddonExport extends AddonBase {
|
|||
).checked;
|
||||
Zotero.Prefs.set("Knowledge4Zotero.exportFile", exportFile);
|
||||
Zotero.Prefs.set("Knowledge4Zotero.exportSingleFile", exportSingleFile);
|
||||
Zotero.Prefs.set("Knowledge4Zotero.exportAutoSync", exportAutoSync);
|
||||
Zotero.Prefs.set("Knowledge4Zotero.embedLink", embedLink);
|
||||
Zotero.Prefs.set("Knowledge4Zotero.exportNote", exportNote);
|
||||
Zotero.Prefs.set("Knowledge4Zotero.exportCopy", exportCopy);
|
||||
|
|
@ -134,6 +171,7 @@ class AddonExport extends AddonBase {
|
|||
this.io.dataOut = {
|
||||
exportFile: exportFile,
|
||||
exportSingleFile: exportSingleFile,
|
||||
exportAutoSync: exportAutoSync,
|
||||
embedLink: embedLink,
|
||||
exportNote: exportNote,
|
||||
exportCopy: exportCopy,
|
||||
|
|
|
|||
|
|
@ -860,7 +860,11 @@ class Knowledge extends AddonBase {
|
|||
}
|
||||
}
|
||||
|
||||
async exportNotesToFile(notes: ZoteroItem[], useEmbed: boolean) {
|
||||
async exportNotesToFile(
|
||||
notes: ZoteroItem[],
|
||||
useEmbed: boolean,
|
||||
useSync: boolean = false
|
||||
) {
|
||||
Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||
this._exportFileDict = [];
|
||||
const filepath = await pick(
|
||||
|
|
@ -948,15 +952,66 @@ class Knowledge extends AddonBase {
|
|||
|
||||
for (const noteInfo of noteLinkDict) {
|
||||
this._exportNote = noteInfo.note;
|
||||
this._export(
|
||||
noteInfo.note,
|
||||
`${Zotero.File.pathToFile(filepath).path}/${noteInfo.filename}`,
|
||||
false
|
||||
);
|
||||
let exportPath = `${Zotero.File.pathToFile(filepath).path}/${
|
||||
noteInfo.filename
|
||||
}`;
|
||||
this._export(noteInfo.note, exportPath, false);
|
||||
if (useSync) {
|
||||
this._Addon.sync.updateNoteSyncStatus(
|
||||
noteInfo.note,
|
||||
Zotero.File.pathToFile(filepath).path,
|
||||
noteInfo.filename
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async syncNotesToFile(notes: ZoteroItem[], filepath: string) {
|
||||
this._exportPath = Zotero.File.pathToFile(filepath).path + "/attachments";
|
||||
// Convert to unix format
|
||||
this._exportPath = this._exportPath.replace(/\\/g, "/");
|
||||
|
||||
// Export every linked note as a markdown file
|
||||
// Find all linked notes that need to be exported
|
||||
let allNoteIds: number[] = [].concat(notes.map((n) => n.id));
|
||||
for (const note of notes) {
|
||||
const subNoteIds = (
|
||||
await Promise.all(
|
||||
note
|
||||
.getNote()
|
||||
.match(/zotero:\/\/note\/\w+\/\w+\//g)
|
||||
.map(async (link) => this.getNoteFromLink(link))
|
||||
)
|
||||
)
|
||||
.filter((res) => res.item)
|
||||
.map((res) => res.item.id);
|
||||
allNoteIds = allNoteIds.concat(subNoteIds);
|
||||
}
|
||||
allNoteIds = new Array(...new Set(allNoteIds));
|
||||
// console.log(allNoteIds);
|
||||
const allNoteItems: ZoteroItem[] = Zotero.Items.get(allNoteIds);
|
||||
const noteLinkDict = allNoteItems.map((_note) => {
|
||||
return {
|
||||
link: this.getNoteLink(_note),
|
||||
id: _note.id,
|
||||
note: _note,
|
||||
filename: this._getFileName(_note),
|
||||
};
|
||||
});
|
||||
this._exportFileDict = noteLinkDict;
|
||||
|
||||
for (const note of notes) {
|
||||
this._exportNote = note;
|
||||
const syncInfo = this._Addon.sync.getNoteSyncStatus(note);
|
||||
let exportPath = `${decodeURIComponent(
|
||||
syncInfo.path
|
||||
)}/${decodeURIComponent(syncInfo.filename)}`;
|
||||
this._export(note, exportPath, false);
|
||||
this._Addon.sync.updateNoteSyncStatus(note);
|
||||
}
|
||||
}
|
||||
|
||||
private async _export(
|
||||
note: ZoteroItem,
|
||||
filename: string,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,214 @@
|
|||
import { AddonBase } from "./base";
|
||||
|
||||
class AddonSync extends AddonBase {
|
||||
triggerTime: number;
|
||||
private io: {
|
||||
dataIn: any;
|
||||
dataOut: any;
|
||||
deferred?: typeof Promise;
|
||||
};
|
||||
private _window: Window;
|
||||
constructor(parent: Knowledge4Zotero) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
doLoad(_window: Window) {
|
||||
this._window = _window;
|
||||
this.io = (this._window as unknown as XULWindow).arguments[0];
|
||||
this.doUpdate();
|
||||
}
|
||||
|
||||
doUpdate() {
|
||||
const syncInfo = this.getNoteSyncStatus(this.io.dataIn);
|
||||
this._window.document
|
||||
.getElementById("Knowledge4Zotero-sync-path")
|
||||
.setAttribute(
|
||||
"value",
|
||||
`${decodeURIComponent(syncInfo.path)}/${decodeURIComponent(
|
||||
syncInfo.filename
|
||||
)}`
|
||||
);
|
||||
|
||||
let lastSync: string;
|
||||
const lastSyncTime = Number(syncInfo.lastsync);
|
||||
const currentTime = new Date().getTime();
|
||||
if (currentTime - lastSyncTime <= 60000) {
|
||||
lastSync = `${Math.round(
|
||||
(currentTime - lastSyncTime) / 1000
|
||||
)} seconds ago.`;
|
||||
} else if (currentTime - lastSyncTime <= 3600000) {
|
||||
lastSync = `${Math.round(
|
||||
(currentTime - lastSyncTime) / 60000
|
||||
)} minutes ago.`;
|
||||
} else {
|
||||
lastSync = new Date(lastSyncTime).toLocaleString();
|
||||
}
|
||||
this._window.document
|
||||
.getElementById("Knowledge4Zotero-sync-lastsync")
|
||||
.setAttribute("value", lastSync);
|
||||
setTimeout(() => {
|
||||
if (!this._window.closed) {
|
||||
this.doUpdate();
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
doUnload() {
|
||||
this.io.deferred && this.io.deferred.resolve();
|
||||
}
|
||||
|
||||
async doAccept() {
|
||||
// Update Settings
|
||||
let enable = (
|
||||
this._window.document.getElementById(
|
||||
"Knowledge4Zotero-sync-enable"
|
||||
) as XUL.Checkbox
|
||||
).checked;
|
||||
if (!enable) {
|
||||
const note = this.io.dataIn;
|
||||
const allNoteIds = await this.getRelatedNoteIds(note);
|
||||
const notes = Zotero.Items.get(allNoteIds);
|
||||
for (const item of notes) {
|
||||
await this.removeSyncNote(item);
|
||||
}
|
||||
this._Addon.views.showProgressWindow(
|
||||
"Better Notes",
|
||||
`Cancel sync of ${notes.length} notes.`
|
||||
);
|
||||
}
|
||||
}
|
||||
doExport() {
|
||||
this.io.dataOut.export = true;
|
||||
(this._window.document.querySelector("dialog") as any).acceptDialog();
|
||||
}
|
||||
|
||||
getSyncNoteIds(): Number[] {
|
||||
const ids = Zotero.Prefs.get("Knowledge4Zotero.syncNoteIds");
|
||||
if (typeof ids === "undefined") {
|
||||
Zotero.Prefs.set("Knowledge4Zotero.syncNoteIds", "");
|
||||
return [];
|
||||
}
|
||||
return ids.split(",").map((id: string) => Number(id));
|
||||
}
|
||||
|
||||
async getRelatedNoteIds(note: ZoteroItem): Promise<Number[]> {
|
||||
let allNoteIds: Number[] = [note.id];
|
||||
const subNoteIds = (
|
||||
await Promise.all(
|
||||
note
|
||||
.getNote()
|
||||
.match(/zotero:\/\/note\/\w+\/\w+\//g)
|
||||
.map(async (link) => this._Addon.knowledge.getNoteFromLink(link))
|
||||
)
|
||||
)
|
||||
.filter((res) => res.item)
|
||||
.map((res) => res.item.id);
|
||||
allNoteIds = allNoteIds.concat(subNoteIds);
|
||||
allNoteIds = new Array(...new Set(allNoteIds));
|
||||
return allNoteIds;
|
||||
}
|
||||
|
||||
addSyncNote(noteItem: ZoteroItem) {
|
||||
const ids = this.getSyncNoteIds();
|
||||
if (ids.includes(noteItem.id)) {
|
||||
return;
|
||||
}
|
||||
ids.push(noteItem.id);
|
||||
Zotero.Prefs.set("Knowledge4Zotero.syncNoteIds", ids.join(","));
|
||||
}
|
||||
|
||||
async removeSyncNote(noteItem: ZoteroItem) {
|
||||
const ids = this.getSyncNoteIds();
|
||||
Zotero.Prefs.set(
|
||||
"Knowledge4Zotero.syncNoteIds",
|
||||
ids.filter((id) => id !== noteItem.id).join(",")
|
||||
);
|
||||
const sycnTag = noteItem.getTags().find((t) => t.tag.includes("sync://"));
|
||||
if (sycnTag) {
|
||||
noteItem.removeTag(sycnTag.tag);
|
||||
}
|
||||
await noteItem.saveTx();
|
||||
}
|
||||
|
||||
getNoteSyncStatus(noteItem: ZoteroItem): any {
|
||||
const sycnInfo = noteItem.getTags().find((t) => t.tag.includes("sync://"));
|
||||
if (!sycnInfo) {
|
||||
return false;
|
||||
}
|
||||
const params = {};
|
||||
sycnInfo.tag
|
||||
.split("?")
|
||||
.pop()
|
||||
.split("&")
|
||||
.forEach((p) => {
|
||||
params[p.split("=")[0]] = p.split("=")[1];
|
||||
});
|
||||
return params;
|
||||
}
|
||||
|
||||
async updateNoteSyncStatus(
|
||||
noteItem: ZoteroItem,
|
||||
path: string = "",
|
||||
filename: string = ""
|
||||
) {
|
||||
this.addSyncNote(noteItem);
|
||||
const syncInfo = this.getNoteSyncStatus(noteItem);
|
||||
const sycnTag = noteItem.getTags().find((t) => t.tag.includes("sync://"));
|
||||
if (sycnTag) {
|
||||
noteItem.removeTag(sycnTag.tag);
|
||||
}
|
||||
noteItem.addTag(
|
||||
`sync://note/?version=${noteItem._version}&path=${
|
||||
path ? encodeURIComponent(path) : syncInfo["path"]
|
||||
}&filename=${
|
||||
filename ? encodeURIComponent(filename) : syncInfo["filename"]
|
||||
}&lastsync=${new Date().getTime()}`,
|
||||
undefined
|
||||
);
|
||||
await noteItem.saveTx();
|
||||
}
|
||||
|
||||
setSync() {
|
||||
const _t = new Date().getTime();
|
||||
this.triggerTime = _t;
|
||||
setTimeout(() => {
|
||||
if (this.triggerTime === _t) {
|
||||
this.doSync();
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
async doSync(force: boolean = false) {
|
||||
Zotero.debug("Better Notes: sync start");
|
||||
const items = Zotero.Items.get(this.getSyncNoteIds());
|
||||
const toExport = {};
|
||||
const forceNoteIds = force
|
||||
? await this.getRelatedNoteIds(this.io.dataIn)
|
||||
: [];
|
||||
for (const item of items) {
|
||||
const syncInfo = this.getNoteSyncStatus(item);
|
||||
const filepath = decodeURIComponent(syncInfo.path);
|
||||
const filename = decodeURIComponent(syncInfo.filename);
|
||||
if (
|
||||
Number(syncInfo.version) < item._version - 1 ||
|
||||
!(await OS.File.exists(`${filepath}/${filename}`)) ||
|
||||
forceNoteIds.includes(item.id)
|
||||
) {
|
||||
if (Object.keys(toExport).includes(filepath)) {
|
||||
toExport[filepath].push(item);
|
||||
} else {
|
||||
toExport[filepath] = [item];
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(toExport);
|
||||
for (const filepath of Object.keys(toExport)) {
|
||||
await this._Addon.knowledge.syncNotesToFile(toExport[filepath], filepath);
|
||||
}
|
||||
if (this._window && !this._window.closed) {
|
||||
this.doUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AddonSync;
|
||||
|
|
@ -3,6 +3,7 @@ declare interface Knowledge4Zotero {
|
|||
views: import("../src/view");
|
||||
wizard: import("../src/wizard");
|
||||
export: import("../src/export");
|
||||
template:import("../src/template");
|
||||
sync: import("../src/sync");
|
||||
template: import("../src/template");
|
||||
knowledge: import("../src/knowledge");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,11 +92,13 @@ declare interface ZoteroItem {
|
|||
isAnnotation: () => boolean;
|
||||
isPDFAttachment: () => boolean;
|
||||
addTag: (name: string, type: number) => boolean;
|
||||
removeTag(tag: string): boolean;
|
||||
itemTypeID: number;
|
||||
libraryID: number;
|
||||
parentID: number;
|
||||
parentItem: ZoteroItem;
|
||||
key: string;
|
||||
_version: any;
|
||||
getField: (
|
||||
name: string,
|
||||
unformatted?: boolean,
|
||||
|
|
|
|||
Loading…
Reference in New Issue