mirror of
https://github.com/laurent22/joplin.git
synced 2024-11-27 08:21:03 +02:00
136 lines
3.6 KiB
TypeScript
136 lines
3.6 KiB
TypeScript
const open = require('open');
|
|
interface LinkStoreEntry {
|
|
link: string;
|
|
noteX: number;
|
|
noteY: number;
|
|
}
|
|
|
|
class LinkSelector {
|
|
noteId_: string;
|
|
scrollTop_: number;
|
|
renderedText_: string;
|
|
currentLinkIndex_: number;
|
|
linkStore_: LinkStoreEntry[];
|
|
linkRegex_: RegExp;
|
|
|
|
constructor() {
|
|
this.noteId_ = null;
|
|
this.scrollTop_ = null; // used so 'o' won't open unhighlighted link after scrolling
|
|
this.renderedText_ = null;
|
|
this.currentLinkIndex_ = null;
|
|
this.linkStore_ = null;
|
|
this.linkRegex_ = /http:\/\/[0-9.]+:[0-9]+\/[0-9]+/g;
|
|
}
|
|
|
|
get link(): string | null {
|
|
if (this.currentLinkIndex_ === null) return null;
|
|
return this.linkStore_[this.currentLinkIndex_].link;
|
|
}
|
|
|
|
get noteX(): number | null {
|
|
if (this.currentLinkIndex_ === null) return null;
|
|
return this.linkStore_[this.currentLinkIndex_].noteX;
|
|
}
|
|
|
|
get noteY(): number | null {
|
|
if (this.currentLinkIndex_ === null) return null;
|
|
return this.linkStore_[this.currentLinkIndex_].noteY;
|
|
}
|
|
|
|
findLinks(renderedText: string): LinkStoreEntry[] {
|
|
const newLinkStore: LinkStoreEntry[] = [];
|
|
const lines: string[] = renderedText.split('\n');
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const r = (lines[i] as any).matchAll(this.linkRegex_);
|
|
const matches = [...r];
|
|
matches.forEach((_e, n) => {
|
|
newLinkStore.push(
|
|
{
|
|
link: matches[n][0],
|
|
noteX: matches[n].index,
|
|
noteY: i,
|
|
}
|
|
);
|
|
});
|
|
}
|
|
return newLinkStore;
|
|
}
|
|
|
|
updateText(renderedText: string): void {
|
|
this.currentLinkIndex_ = null;
|
|
this.renderedText_ = renderedText;
|
|
this.linkStore_ = this.findLinks(this.renderedText_);
|
|
}
|
|
|
|
updateNote(textWidget: any): void {
|
|
this.noteId_ = textWidget.noteId;
|
|
this.scrollTop_ = textWidget.scrollTop_;
|
|
this.updateText(textWidget.renderedText_);
|
|
}
|
|
|
|
scrollWidget(textWidget: any): void {
|
|
if (this.currentLinkIndex_ === null) return;
|
|
|
|
const noteY = this.linkStore_[this.currentLinkIndex_].noteY;
|
|
|
|
let viewBoxMin = textWidget.scrollTop_ + 1;
|
|
let viewBoxMax = viewBoxMin + textWidget.innerHeight - 2;
|
|
|
|
if (noteY < viewBoxMin) {
|
|
for (; noteY < viewBoxMin; textWidget.pageUp()) {
|
|
viewBoxMin = textWidget.scrollTop_;
|
|
viewBoxMax = viewBoxMin + textWidget.innerHeight;
|
|
}
|
|
return;
|
|
|
|
} else if (noteY > viewBoxMax) {
|
|
for (; noteY > viewBoxMax; textWidget.pageDown()) {
|
|
viewBoxMin = textWidget.scrollTop_;
|
|
viewBoxMax = viewBoxMin + textWidget.innerHeight;
|
|
}
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
changeLink(textWidget: any, offset: number): void | null {
|
|
if (textWidget.noteId !== this.noteId_) {
|
|
this.updateNote(textWidget);
|
|
this.changeLink(textWidget, offset);
|
|
return;
|
|
}
|
|
if (textWidget.renderedText_ !== this.renderedText_) {
|
|
this.updateText(textWidget.renderedText_);
|
|
this.changeLink(textWidget, offset);
|
|
return;
|
|
}
|
|
if (textWidget.scrollTop_ !== this.scrollTop_) this.scrollTop_ = textWidget.scrollTop_;
|
|
|
|
if (!this.linkStore_.length) return null;
|
|
|
|
let offsetMod = (offset + this.currentLinkIndex_) % this.linkStore_.length;
|
|
|
|
if (this.currentLinkIndex_ === null) {
|
|
if (offsetMod < 0) this.currentLinkIndex_ = this.linkStore_.length + offsetMod;
|
|
else if (!offsetMod) this.currentLinkIndex_ = 0;
|
|
else this.currentLinkIndex_ = offsetMod - 1;
|
|
return;
|
|
}
|
|
|
|
if (offsetMod < 0) offsetMod = this.linkStore_.length + offsetMod;
|
|
|
|
this.currentLinkIndex_ = offsetMod;
|
|
return;
|
|
}
|
|
|
|
openLink(textWidget: any): void {
|
|
if (textWidget.noteId !== this.noteId_) return;
|
|
if (textWidget.renderedText_ !== this.renderedText_) return;
|
|
if (textWidget.scrollTop_ !== this.scrollTop_) return;
|
|
open(this.linkStore_[this.currentLinkIndex_].link);
|
|
}
|
|
}
|
|
|
|
export default LinkSelector;
|
|
|