mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
tabs WIP
This commit is contained in:
parent
7f0c92c56b
commit
b1d0cef33b
@ -50,8 +50,7 @@
|
|||||||
`
|
`
|
||||||
|
|
||||||
const defaultTapProperties = {
|
const defaultTapProperties = {
|
||||||
title: 'New tab',
|
title: 'New tab'
|
||||||
favicon: false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let instanceId = 0
|
let instanceId = 0
|
||||||
|
@ -17,10 +17,6 @@ import noteDetailRelationMap from "./note_detail_relation_map.js";
|
|||||||
|
|
||||||
const $noteTabContentsContainer = $("#note-tab-container");
|
const $noteTabContentsContainer = $("#note-tab-container");
|
||||||
|
|
||||||
const el = $('.chrome-tabs')[0];
|
|
||||||
const chromeTabs = new ChromeTabs();
|
|
||||||
chromeTabs.init(el);
|
|
||||||
|
|
||||||
const componentClasses = {
|
const componentClasses = {
|
||||||
'code': noteDetailCode,
|
'code': noteDetailCode,
|
||||||
'text': noteDetailText,
|
'text': noteDetailText,
|
||||||
@ -31,12 +27,25 @@ const componentClasses = {
|
|||||||
'relation-map': noteDetailRelationMap
|
'relation-map': noteDetailRelationMap
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let tabIdCounter = 1;
|
||||||
|
|
||||||
class NoteContext {
|
class NoteContext {
|
||||||
constructor(note, openOnBackground) {
|
constructor(chromeTabs, note, openOnBackground) {
|
||||||
|
this.tabId = tabIdCounter++;
|
||||||
|
this.chromeTabs = chromeTabs;
|
||||||
/** @type {NoteFull} */
|
/** @type {NoteFull} */
|
||||||
this.note = note;
|
this.note = note;
|
||||||
this.noteId = note.noteId;
|
this.noteId = note.noteId;
|
||||||
this.$noteTabContent = $noteTabContentsContainer.find(`[data-note-id="${this.noteId}"]`);
|
|
||||||
|
this.$noteTabContent = $(".note-tab-content-template").clone();
|
||||||
|
this.$noteTabContent.removeClass('note-tab-content-template');
|
||||||
|
this.$noteTabContent.attr('data-note-id', this.noteId);
|
||||||
|
this.$noteTabContent.attr('data-tab-id', this.tabId);
|
||||||
|
|
||||||
|
$noteTabContentsContainer.append(this.$noteTabContent);
|
||||||
|
|
||||||
|
console.log(`Creating note tab ${this.tabId} for ${this.noteId}`);
|
||||||
|
|
||||||
this.$noteTitle = this.$noteTabContent.find(".note-title");
|
this.$noteTitle = this.$noteTabContent.find(".note-title");
|
||||||
this.$noteDetailComponents = this.$noteTabContent.find(".note-detail-component");
|
this.$noteDetailComponents = this.$noteTabContent.find(".note-detail-component");
|
||||||
this.$protectButton = this.$noteTabContent.find(".protect-button");
|
this.$protectButton = this.$noteTabContent.find(".protect-button");
|
||||||
@ -58,9 +67,9 @@ class NoteContext {
|
|||||||
treeService.setNoteTitle(this.noteId, title);
|
treeService.setNoteTitle(this.noteId, title);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tab = chromeTabs.addTab({
|
this.tab = this.chromeTabs.addTab({
|
||||||
title: note.title,
|
title: note.title,
|
||||||
favicon: false
|
id: this.tabId
|
||||||
}, {
|
}, {
|
||||||
background: openOnBackground
|
background: openOnBackground
|
||||||
});
|
});
|
||||||
@ -73,9 +82,11 @@ class NoteContext {
|
|||||||
this.note = note;
|
this.note = note;
|
||||||
this.$noteTabContent.attr('data-note-id', note.noteId);
|
this.$noteTabContent.attr('data-note-id', note.noteId);
|
||||||
|
|
||||||
chromeTabs.updateTab(this.tab, {title: note.title});
|
this.chromeTabs.updateTab(this.tab, {title: note.title});
|
||||||
|
|
||||||
this.attributes.invalidateAttributes();
|
this.attributes.invalidateAttributes();
|
||||||
|
|
||||||
|
console.log(`Switched tab ${this.tabId} to ${this.noteId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getComponent(type) {
|
getComponent(type) {
|
||||||
|
@ -12,6 +12,10 @@ import bundleService from "./bundle.js";
|
|||||||
import utils from "./utils.js";
|
import utils from "./utils.js";
|
||||||
import importDialog from "../dialogs/import.js";
|
import importDialog from "../dialogs/import.js";
|
||||||
|
|
||||||
|
const chromeTabsEl = document.querySelector('.chrome-tabs');
|
||||||
|
const chromeTabs = new ChromeTabs();
|
||||||
|
chromeTabs.init(chromeTabsEl);
|
||||||
|
|
||||||
const $noteTabContentsContainer = $("#note-tab-container");
|
const $noteTabContentsContainer = $("#note-tab-container");
|
||||||
const $savedIndicator = $(".saved-indicator");
|
const $savedIndicator = $(".saved-indicator");
|
||||||
|
|
||||||
@ -84,7 +88,7 @@ async function handleProtectedSession() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @type {NoteContext[]} */
|
/** @type {NoteContext[]} */
|
||||||
const noteContexts = [];
|
let noteContexts = [];
|
||||||
|
|
||||||
/** @returns {NoteContext} */
|
/** @returns {NoteContext} */
|
||||||
function getContext(noteId) {
|
function getContext(noteId) {
|
||||||
@ -107,9 +111,11 @@ function getActiveContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showTab(noteId) {
|
function showTab(tabId) {
|
||||||
|
tabId = parseInt(tabId);
|
||||||
|
|
||||||
for (const ctx of noteContexts) {
|
for (const ctx of noteContexts) {
|
||||||
ctx.$noteTabContent.toggle(ctx.noteId === noteId);
|
ctx.$noteTabContent.toggle(ctx.tabId === tabId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,19 +124,12 @@ async function loadNoteDetail(noteId, newTab = false) {
|
|||||||
let ctx;
|
let ctx;
|
||||||
|
|
||||||
if (noteContexts.length === 0 || newTab) {
|
if (noteContexts.length === 0 || newTab) {
|
||||||
const $tabContent = $(".note-tab-content-template").clone();
|
|
||||||
|
|
||||||
$tabContent.removeClass('note-tab-content-template');
|
|
||||||
$tabContent.attr('data-note-id', noteId);
|
|
||||||
|
|
||||||
$noteTabContentsContainer.append($tabContent);
|
|
||||||
|
|
||||||
// if it's a new tab explicitly by user then it's in background
|
// if it's a new tab explicitly by user then it's in background
|
||||||
ctx = new NoteContext(loadedNote, newTab);
|
ctx = new NoteContext(chromeTabs, loadedNote, newTab);
|
||||||
noteContexts.push(ctx);
|
noteContexts.push(ctx);
|
||||||
|
|
||||||
if (!newTab) {
|
if (!newTab) {
|
||||||
showTab(noteId);
|
showTab(ctx.tabId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -270,8 +269,32 @@ $noteTabContentsContainer.on("drop", e => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelector('.chrome-tabs')
|
chromeTabsEl.addEventListener('activeTabChange', ({ detail }) => {
|
||||||
.addEventListener('activeTabChange', ({ detail }) => showTab(detail.tabEl.getAttribute('data-note-id')));
|
const tabId = detail.tabEl.getAttribute('data-tab-id');
|
||||||
|
|
||||||
|
showTab(tabId);
|
||||||
|
|
||||||
|
console.log(`Activated tab ${tabId}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
chromeTabsEl.addEventListener('tabRemove', ({ detail }) => {
|
||||||
|
const tabId = parseInt(detail.tabEl.getAttribute('data-tab-id'));
|
||||||
|
|
||||||
|
noteContexts = noteContexts.filter(nc => nc.tabId !== tabId);
|
||||||
|
|
||||||
|
console.log(`Removed tab ${tabId}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (utils.isElectron()) {
|
||||||
|
utils.bindShortcut('ctrl+w', () => {
|
||||||
|
if (noteContexts.length === 1) {
|
||||||
|
// at least one tab must be present
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chromeTabs.removeTab(chromeTabs.activeTabEl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// this makes sure that when user e.g. reloads the page or navigates away from the page, the note's content is saved
|
// this makes sure that when user e.g. reloads the page or navigates away from the page, the note's content is saved
|
||||||
// this sends the request asynchronously and doesn't wait for result
|
// this sends the request asynchronously and doesn't wait for result
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import utils from './utils.js';
|
import utils from './utils.js';
|
||||||
import infoService from "./info.js";
|
import infoService from "./info.js";
|
||||||
|
|
||||||
|
const REQUEST_LOGGING_ENABLED = false;
|
||||||
|
|
||||||
function getHeaders() {
|
function getHeaders() {
|
||||||
// headers need to be lowercase because node.js automatically converts them to lower case
|
// headers need to be lowercase because node.js automatically converts them to lower case
|
||||||
// so hypothetical protectedSessionId becomes protectedsessionid on the backend
|
// so hypothetical protectedSessionId becomes protectedsessionid on the backend
|
||||||
@ -45,7 +47,9 @@ async function call(method, url, data) {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
reqResolves[requestId] = resolve;
|
reqResolves[requestId] = resolve;
|
||||||
|
|
||||||
console.log(utils.now(), "Request #" + requestId + " to " + method + " " + url);
|
if (REQUEST_LOGGING_ENABLED) {
|
||||||
|
console.log(utils.now(), "Request #" + requestId + " to " + method + " " + url);
|
||||||
|
}
|
||||||
|
|
||||||
ipc.send('server-request', {
|
ipc.send('server-request', {
|
||||||
requestId: requestId,
|
requestId: requestId,
|
||||||
@ -89,7 +93,9 @@ if (utils.isElectron()) {
|
|||||||
const ipc = require('electron').ipcRenderer;
|
const ipc = require('electron').ipcRenderer;
|
||||||
|
|
||||||
ipc.on('server-response', (event, arg) => {
|
ipc.on('server-response', (event, arg) => {
|
||||||
console.log(utils.now(), "Response #" + arg.requestId + ": " + arg.statusCode);
|
if (REQUEST_LOGGING_ENABLED) {
|
||||||
|
console.log(utils.now(), "Response #" + arg.requestId + ": " + arg.statusCode);
|
||||||
|
}
|
||||||
|
|
||||||
reqResolves[arg.requestId](arg.body);
|
reqResolves[arg.requestId](arg.body);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user