Skip to content

Commit

Permalink
V3.3.0 beta prerelease (#66)
Browse files Browse the repository at this point in the history
* dropdown list available when tabs overflow

* custom citation key implemented

* improve GeneralTab style

* implemented pdf darkmode

* able to pin multiple peekers in pdf

* clean up code

* implement HoverPane for markdown editor

* AnnotCard uses Vditor to render

* move some setting related functions to appState.ts

* upgrade vditor
  • Loading branch information
HuntFeng authored Sep 1, 2023
1 parent 218f66a commit bc88f3a
Show file tree
Hide file tree
Showing 41 changed files with 1,187 additions and 577 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ This project is made possible by the following open source projects.
- citation-js
- cytoscape
- golden-layout
- katex
- pdf.js
- vditor
- Pouchdb
Expand Down
1 change: 0 additions & 1 deletion README.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ yarn build # 编译测试版
- citation-js
- cytoscape
- golden-layout
- katex
- pdf.js
- vditor
- Pouchdb
Expand Down
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "research-helper",
"version": "3.2.0-beta",
"version": "3.3.0-beta",
"description": "A paper / book / note management tool",
"productName": "Research Helper",
"author": "Hunt Feng <[email protected]>",
Expand Down Expand Up @@ -34,7 +34,6 @@
"electron-updater": "^5.3.0",
"events": "^3.3.0",
"golden-layout": "^2.6.0",
"katex": "^0.16.4",
"konva": "^9.2.0",
"nodejs-file-downloader": "^4.11.2",
"pdfjs-dist": "^3.7.107",
Expand All @@ -44,7 +43,7 @@
"quasar": "^2.11.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"vditor": "3.8.17",
"vditor": "^3.9.5",
"veaury": "^2.3.12",
"vue": "^3.0.0",
"vue-i18n": "^9.0.0",
Expand All @@ -57,7 +56,7 @@
"@quasar/quasar-app-extension-testing-e2e-cypress": "^5.1.0",
"@quasar/quasar-app-extension-testing-unit-vitest": "^0.1.0",
"@types/cytoscape": "^3.19.9",
"@types/katex": "^0.16.0",
"@types/lodash": "^4.14.197",
"@types/node": "^12.20.21",
"@types/pouchdb": "^6.4.0",
"@types/react": "^18.2.0",
Expand Down
55 changes: 46 additions & 9 deletions src/backend/database/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import PouchDB from "pouchdb";
import Find from "pouchdb-find";
import { generateCiteKey } from "../project/meta";
import { Project } from "./models";
PouchDB.plugin(Find);
const db = new PouchDB("mydb");

// for details of compacting database, see https://pouchdb.com/guides/compact-and-destroy.html
const db = new PouchDB("mydb", { auto_compaction: true, revs_limit: 10 });

db.createIndex({
index: {
Expand All @@ -19,18 +23,51 @@ db.createIndex({
},
});

// compacting the database
// for details, see https://pouchdb.com/guides/compact-and-destroy.html
db.compact()
.then((info) => {
console.log(info);
// TODO: remove this few more versions later
// add timestamps to data
// remove all edge data
// add citation-key to project
db.allDocs({ include_docs: true })
.then((result) => {
let docs = [];
for (let row of result.rows as { doc: any }[]) {
let flag = false;
let doc = row.doc as {
dataType: string;
timestampAdded?: number;
timestampModified?: number;
_deleted?: boolean;
};
switch (doc.dataType) {
case "project":
if (!(doc as Project)["citation-key"])
(doc as Project)["citation-key"] = generateCiteKey(doc as Project);
flag = true;
case "folder":
case "note":
case "pdfAnnotation":
if (!doc.timestampAdded) {
doc.timestampAdded = Date.now();
doc.timestampModified = Date.now();
flag = true;
}
break;
case "edge":
doc._deleted = true;
flag = true;
default:
break;
}
if (flag) docs.push(doc);
}
db.bulkDocs(docs);
})
.catch((error) => {
console.log(error);
.catch((err) => {
console.log(err);
});

// for debug use
if ((process.env.DEV || process.env.DEBUGGING) && !process.env.TEST) {
// for debug use
const remotedb = new PouchDB("http://localhost:3000/mydb");
PouchDB.sync("mydb", "http://localhost:3000/mydb", {
live: true,
Expand Down
12 changes: 7 additions & 5 deletions src/backend/database/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ interface Reference {
*/
export interface Meta {
id: string; // citation id
"citation-label": string; // citatin label
"citation-label"?: string; // citatin label
"citation-key": string; // used to cite for bibtex
type?: string; // article / book / conference-paper ...
title: string; // article / book title
author?: Author[]; // array of authors [{family: "Feng", given: "Feng"}, {literal: "John"}]
author: Author[]; // array of authors [{family: "Feng", given: "Feng"}, {literal: "John"}]
abstract?: string; // article abstract
year?: string;
issued?: { "date-parts": Array<any> }; // issued date
DOI?: string; // Digital Object Identity
ISBN?: string; // ISBN of a book
Expand Down Expand Up @@ -146,6 +146,7 @@ export interface PDFState {
currentScaleValue: "page-width" | "page-height" | string;
spreadMode: SpreadMode; // 0: no spread, 1: odd spread, 2: even spread
tool: AnnotationType;
darkMode: boolean;
color: string; // hex value
scrollLeft: number; // current scrollLeft position
scrollTop: number; // current scrollTop position
Expand Down Expand Up @@ -237,10 +238,11 @@ export interface RenderEvt {
* App global settings
**************************************************/
export interface Settings {
theme: "dark" | "light"; // dark by default
language: "en_US" | "zh_CN"; // en_US by default
theme: string; // dark by default
language: string; // en_US by default
storagePath: string; // select by user
fontSize: string; // 16px by default
citeKeyRule: string; // "author_title_year" by default
}

export interface AppState {
Expand Down
2 changes: 0 additions & 2 deletions src/backend/pdfannotation/annotationFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,6 @@ export default class AnnotationFactory {
content: "",
} as AnnotationData;

console.log("annotData", annotData);

return this.build(annotData);
}
}
16 changes: 0 additions & 16 deletions src/backend/pdfannotation/annotationStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,6 @@ export default class AnnotationStore {
})
).docs as AnnotationData[];

// TODO: remove this few more versions later
let flag = false;
for (let annotData of annotDatas)
if (!annotData.timestampAdded) {
annotData.timestampAdded = Date.now();
annotData.timestampModified = Date.now();
flag = true;
}
if (flag) {
let responses = await db.bulkDocs(annotDatas);
for (let i in responses) {
let rev = responses[i].rev;
if (rev) annotDatas[i]._rev = rev;
}
}

return annotDatas;
} catch (err) {
console.log(err);
Expand Down
77 changes: 49 additions & 28 deletions src/backend/pdfreader/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { debounce } from "quasar";
import { nextTick, reactive, ref } from "vue";
import { AnnotationStore, AnnotationFactory } from "../pdfannotation";
import { PeekManager } from "./pdfpeek";
import { PeekManager } from "./peekManager";
import {
PDFFindController,
PDFPageView,
Expand All @@ -24,13 +24,13 @@ pdfjsLib.GlobalWorkerOptions.workerSrc =

export default class PDFApplication {
container: HTMLDivElement | undefined;
peekContainer: HTMLDivElement | undefined;
eventBus: pdfjsViewer.EventBus | undefined;
pdfLinkService: pdfjsViewer.PDFLinkService | undefined;
pdfFindController: pdfjsViewer.PDFFindController | undefined;
pdfViewer: pdfjsViewer.PDFViewer | undefined;
peekManager: PeekManager | undefined;
peekManager: PeekManager;
pdfDocument: pdfjsLib.PDFDocumentProxy | undefined;

annotStore: AnnotationStore;
annotFactory: AnnotationFactory;

Expand All @@ -50,6 +50,7 @@ export default class PDFApplication {
this.projectId = projectId;
this.annotStore = new AnnotationStore(projectId);
this.annotFactory = new AnnotationFactory(projectId);
this.peekManager = new PeekManager();
// make saveState a debounce function
// it ignores the signals 500ms after each call
this.saveState = debounce(this._saveState, 500);
Expand All @@ -72,7 +73,7 @@ export default class PDFApplication {
} as PDFState);
}

init(container: HTMLDivElement, peekContainer: HTMLDivElement) {
init(container: HTMLDivElement) {
const eventBus = new pdfjsViewer.EventBus();
const pdfLinkService = new pdfjsViewer.PDFLinkService({
eventBus,
Expand Down Expand Up @@ -102,12 +103,10 @@ export default class PDFApplication {
pdfLinkService.setViewer(pdfViewer);

this.container = container;
this.peekContainer = peekContainer;
this.eventBus = eventBus;
this.pdfLinkService = pdfLinkService;
this.pdfFindController = pdfFindController;
this.pdfViewer = pdfViewer;
this.peekManager = new PeekManager(container, peekContainer);
this.pdfDocument = undefined; // initialize in loadPDF

// install internal event listener
Expand All @@ -120,6 +119,7 @@ export default class PDFApplication {
this.changeSpreadMode(this.state.spreadMode);
this.changeScale({ scale: this.state.currentScale });
this.changeTool(this.state.tool);
this.changeViewMode(this.state.darkMode);
if (this.pdfViewer) this.state.pagesCount = this.pdfViewer.pagesCount;
this.ready.value = true;
});
Expand All @@ -132,7 +132,15 @@ export default class PDFApplication {
if (!link) return;
if (section.hasAttribute("data-internal-link")) {
// peek internal links
if (this.peekManager) this.peekManager.peek(link);
link.onmouseover = () => {
if (!link) return;
let timeoutId = setTimeout(() => {
if (!link) return;
if (this.peekManager) this.peekManager.create(link);
}, 500);

link.onmouseleave = () => clearTimeout(timeoutId);
};
} else {
// external links must open using default browser
let href = link.href;
Expand Down Expand Up @@ -223,7 +231,6 @@ export default class PDFApplication {
if (process.env.DEV)
cMapUrl = new URL("../../../cmaps/", import.meta.url).href;
else {
console.log("url?", import.meta.url);
cMapUrl = new URL("cmaps/", import.meta.url).href;
}
let buffer = window.fs.readFileSync(filePath);
Expand All @@ -237,7 +244,7 @@ export default class PDFApplication {
if (this.pdfFindController)
this.pdfFindController.setDocument(this.pdfDocument);
if (this.pdfViewer) this.pdfViewer.setDocument(this.pdfDocument);
if (this.peekManager) this.peekManager.loadPDF(filePath);
this.peekManager.setDocument(this.pdfDocument);
this.getTOC();
this.getPageLabels();
}
Expand All @@ -248,25 +255,27 @@ export default class PDFApplication {
selector: { dataType: "pdfState", projectId: projectId },
});

let state = result.docs[0] as PDFState;
if (!!!state) {
// default state
state = {
dataType: "pdfState",
projectId: projectId,
pagesCount: 0,
currentPageNumber: 1,
currentScale: 1,
currentScaleValue: "1",
spreadMode: 0,
tool: "cursor",
color: "#FFFF00",
inkThickness: 5,
inkOpacity: 100,
scrollLeft: 0,
scrollTop: 0,
} as PDFState;
}
// default state
let state = {
_id: "",
_rev: "",
dataType: "pdfState",
projectId: projectId,
pagesCount: 0,
currentPageNumber: 1,
currentScale: 1,
currentScaleValue: "1",
spreadMode: 0,
darkMode: false,
tool: "cursor",
color: "#FFFF00",
inkThickness: 5,
inkOpacity: 100,
scrollLeft: 0,
scrollTop: 0,
} as PDFState;
// doing this we can make sure if anything missing from db, the default values are there
Object.assign(state, result.docs[0] as PDFState);
Object.assign(this.state, state);
return state;
} catch (error) {
Expand Down Expand Up @@ -341,6 +350,18 @@ export default class PDFApplication {
this.state.color = color;
}

changeViewMode(darkMode: boolean) {
this.state.darkMode = darkMode;
let viewer = this.container?.querySelector(
".pdfViewer"
) as HTMLElement | null;
if (!viewer) return;
if (darkMode)
viewer.style.filter =
"invert(64%) contrast(228%) brightness(80%) hue-rotate(180deg)";
else viewer.style.filter = "unset";
}

changeInkThickness(thickness: number) {
this.state.inkThickness = thickness;
}
Expand Down
Loading

0 comments on commit bc88f3a

Please sign in to comment.