mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-27 18:12:29 +08:00

git-subtree-dir: apps/web-clipper git-subtree-mainline: b0e519071893ce9434dd3bb3a568b3e41332c718 git-subtree-split: 786d249a6effe0262859d05e6cb1737e5fc8bdd8
226 lines
5.2 KiB
JavaScript
226 lines
5.2 KiB
JavaScript
const PROTOCOL_VERSION_MAJOR = 1;
|
|
|
|
function isDevEnv() {
|
|
const manifest = browser.runtime.getManifest();
|
|
|
|
return manifest.name.endsWith('(dev)');
|
|
}
|
|
|
|
class TriliumServerFacade {
|
|
constructor() {
|
|
this.triggerSearchForTrilium();
|
|
|
|
// continually scan for changes (if e.g. desktop app is started after browser)
|
|
setInterval(() => this.triggerSearchForTrilium(), 60 * 1000);
|
|
}
|
|
|
|
async sendTriliumSearchStatusToPopup() {
|
|
try {
|
|
await browser.runtime.sendMessage({
|
|
name: "trilium-search-status",
|
|
triliumSearch: this.triliumSearch
|
|
});
|
|
}
|
|
catch (e) {} // nothing might be listening
|
|
}
|
|
async sendTriliumSearchNoteToPopup(){
|
|
try{
|
|
await browser.runtime.sendMessage({
|
|
name: "trilium-previously-visited",
|
|
searchNote: this.triliumSearchNote
|
|
})
|
|
|
|
}
|
|
catch (e) {} // nothing might be listening
|
|
}
|
|
|
|
setTriliumSearchNote(st){
|
|
this.triliumSearchNote = st;
|
|
this.sendTriliumSearchNoteToPopup();
|
|
}
|
|
|
|
setTriliumSearch(ts) {
|
|
this.triliumSearch = ts;
|
|
|
|
this.sendTriliumSearchStatusToPopup();
|
|
}
|
|
|
|
setTriliumSearchWithVersionCheck(json, resp) {
|
|
const [major, minor] = json.protocolVersion
|
|
.split(".")
|
|
.map(chunk => parseInt(chunk));
|
|
|
|
// minor version is intended to be used to dynamically limit features provided by extension
|
|
// if some specific Trilium API is not supported. So far not needed.
|
|
|
|
if (major !== PROTOCOL_VERSION_MAJOR) {
|
|
this.setTriliumSearch({
|
|
status: 'version-mismatch',
|
|
extensionMajor: PROTOCOL_VERSION_MAJOR,
|
|
triliumMajor: major
|
|
});
|
|
}
|
|
else {
|
|
this.setTriliumSearch(resp);
|
|
}
|
|
}
|
|
|
|
async triggerSearchForTrilium() {
|
|
this.setTriliumSearch({ status: 'searching' });
|
|
|
|
try {
|
|
const port = await this.getPort();
|
|
|
|
console.debug('Trying port ' + port);
|
|
|
|
const resp = await fetch(`http://127.0.0.1:${port}/api/clipper/handshake`);
|
|
|
|
const text = await resp.text();
|
|
|
|
console.log("Received response:", text);
|
|
|
|
const json = JSON.parse(text);
|
|
|
|
if (json.appName === 'trilium') {
|
|
this.setTriliumSearchWithVersionCheck(json, {
|
|
status: 'found-desktop',
|
|
port: port,
|
|
url: 'http://127.0.0.1:' + port
|
|
});
|
|
|
|
return;
|
|
}
|
|
}
|
|
catch (error) {
|
|
// continue
|
|
}
|
|
|
|
const {triliumServerUrl} = await browser.storage.sync.get("triliumServerUrl");
|
|
const {authToken} = await browser.storage.sync.get("authToken");
|
|
|
|
if (triliumServerUrl && authToken) {
|
|
try {
|
|
const resp = await fetch(triliumServerUrl + '/api/clipper/handshake', {
|
|
headers: {
|
|
Authorization: authToken
|
|
}
|
|
});
|
|
|
|
const text = await resp.text();
|
|
|
|
console.log("Received response:", text);
|
|
|
|
const json = JSON.parse(text);
|
|
|
|
if (json.appName === 'trilium') {
|
|
this.setTriliumSearchWithVersionCheck(json, {
|
|
status: 'found-server',
|
|
url: triliumServerUrl,
|
|
token: authToken
|
|
});
|
|
|
|
return;
|
|
}
|
|
}
|
|
catch (e) {
|
|
console.log("Request to the configured server instance failed with:", e);
|
|
}
|
|
}
|
|
|
|
// if all above fails it's not found
|
|
this.setTriliumSearch({ status: 'not-found' });
|
|
}
|
|
|
|
async triggerSearchNoteByUrl(noteUrl) {
|
|
const resp = await triliumServerFacade.callService('GET', 'notes-by-url/' + encodeURIComponent(noteUrl))
|
|
let newStatus = {
|
|
status: 'not-found',
|
|
noteId: null
|
|
}
|
|
if (resp && resp.noteId) {
|
|
newStatus.noteId = resp.noteId;
|
|
newStatus.status = 'found';
|
|
}
|
|
this.setTriliumSearchNote(newStatus);
|
|
}
|
|
async waitForTriliumSearch() {
|
|
return new Promise((res, rej) => {
|
|
const checkStatus = () => {
|
|
if (this.triliumSearch.status === "searching") {
|
|
setTimeout(checkStatus, 500);
|
|
}
|
|
else if (this.triliumSearch.status === 'not-found') {
|
|
rej(new Error("Trilium instance has not been found."));
|
|
}
|
|
else {
|
|
res();
|
|
}
|
|
};
|
|
|
|
checkStatus();
|
|
});
|
|
}
|
|
|
|
async getPort() {
|
|
const {triliumDesktopPort} = await browser.storage.sync.get("triliumDesktopPort");
|
|
|
|
if (triliumDesktopPort) {
|
|
return parseInt(triliumDesktopPort);
|
|
}
|
|
else {
|
|
return isDevEnv() ? 37740 : 37840;
|
|
}
|
|
}
|
|
|
|
async callService(method, path, body) {
|
|
const fetchOptions = {
|
|
method: method,
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
};
|
|
|
|
if (body) {
|
|
fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
|
|
}
|
|
|
|
try {
|
|
await this.waitForTriliumSearch();
|
|
|
|
fetchOptions.headers.Authorization = this.triliumSearch.token || "";
|
|
fetchOptions.headers['trilium-local-now-datetime'] = this.localNowDateTime();
|
|
|
|
const url = this.triliumSearch.url + "/api/clipper/" + path;
|
|
|
|
console.log(`Sending ${method} request to ${url}`);
|
|
|
|
const response = await fetch(url, fetchOptions);
|
|
|
|
if (!response.ok) {
|
|
throw new Error(await response.text());
|
|
}
|
|
|
|
return await response.json();
|
|
}
|
|
catch (e) {
|
|
console.log("Sending request to trilium failed", e);
|
|
|
|
toast('Your request failed because we could not contact Trilium instance. Please make sure Trilium is running and is accessible.');
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
localNowDateTime() {
|
|
const date = new Date();
|
|
const off = date.getTimezoneOffset();
|
|
const absoff = Math.abs(off);
|
|
return (new Date(date.getTime() - off * 60 * 1000).toISOString().substr(0,23).replace("T", " ") +
|
|
(off > 0 ? '-' : '+') +
|
|
(absoff / 60).toFixed(0).padStart(2,'0') + ':' +
|
|
(absoff % 60).toString().padStart(2,'0'));
|
|
}
|
|
}
|
|
|
|
window.triliumServerFacade = new TriliumServerFacade();
|