mirror of
https://github.com/zadam/trilium.git
synced 2025-01-16 12:08:03 +08:00
basic opening and switching tabs
This commit is contained in:
parent
c7b5784123
commit
39093cbc4c
6 changed files with 44 additions and 39 deletions
|
@ -9,7 +9,7 @@ import noteDetailService from "./note_detail.js";
|
|||
const $attributeList = $("#attribute-list");
|
||||
const $attributeListInner = $("#attribute-list-inner");
|
||||
const $promotedAttributesContainer = $("#note-detail-promoted-attributes");
|
||||
const $savedIndicator = $("#saved-indicator");
|
||||
const $savedIndicator = $(".saved-indicator");
|
||||
|
||||
let attributePromise;
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ async function initContextMenu(event, contextMenu) {
|
|||
|
||||
contextMenu.selectContextMenuItem(e, cmd);
|
||||
|
||||
hideContextMenu();
|
||||
|
||||
// it's important to stop the propagation especially for sub-menus, otherwise the event
|
||||
// might be handled again by top-level menu
|
||||
return false;
|
||||
|
|
|
@ -19,10 +19,6 @@ const el = $('.chrome-tabs')[0];
|
|||
const chromeTabs = new ChromeTabs();
|
||||
chromeTabs.init(el);
|
||||
|
||||
el.addEventListener('activeTabChange', ({detail}) => console.log('Active tab changed', detail.tabEl));
|
||||
el.addEventListener('tabAdd', ({detail}) => console.log('Tab added', detail.tabEl));
|
||||
el.addEventListener('tabRemove', ({detail}) => console.log('Tab removed', detail.tabEl));
|
||||
|
||||
const componentClasses = {
|
||||
'code': noteDetailCode,
|
||||
'text': noteDetailText,
|
||||
|
@ -34,7 +30,7 @@ const componentClasses = {
|
|||
};
|
||||
|
||||
class NoteContext {
|
||||
constructor(note) {
|
||||
constructor(note, openOnBackground) {
|
||||
/** @type {NoteFull} */
|
||||
this.note = note;
|
||||
this.noteId = note.noteId;
|
||||
|
@ -45,6 +41,7 @@ class NoteContext {
|
|||
this.$unprotectButton = this.$noteTabContent.find(".unprotect-button");
|
||||
this.$childrenOverview = this.$noteTabContent.find(".children-overview");
|
||||
this.$scriptArea = this.$noteTabContent.find(".note-detail-script-area");
|
||||
this.$savedIndicator = this.$noteTabContent.find(".saved-indicator");
|
||||
this.isNoteChanged = false;
|
||||
this.components = {};
|
||||
|
||||
|
@ -59,7 +56,11 @@ class NoteContext {
|
|||
this.tab = chromeTabs.addTab({
|
||||
title: note.title,
|
||||
favicon: false
|
||||
}, {
|
||||
background: openOnBackground
|
||||
});
|
||||
|
||||
this.tab.setAttribute('data-note-id', this.noteId);
|
||||
}
|
||||
|
||||
setNote(note) {
|
||||
|
@ -102,10 +103,10 @@ class NoteContext {
|
|||
protectedSessionHolder.touchProtectedSession();
|
||||
}
|
||||
|
||||
$savedIndicator.fadeIn();
|
||||
this.$savedIndicator.fadeIn();
|
||||
|
||||
// run async
|
||||
bundleService.executeRelationBundles(getActiveNote(), 'runOnNoteChange');
|
||||
bundleService.executeRelationBundles(this.note, 'runOnNoteChange');
|
||||
}
|
||||
|
||||
async saveNoteIfChanged() {
|
||||
|
@ -121,7 +122,7 @@ class NoteContext {
|
|||
|
||||
this.isNoteChanged = true;
|
||||
|
||||
$savedIndicator.fadeOut();
|
||||
this.$savedIndicator.fadeOut();
|
||||
}
|
||||
|
||||
async showChildrenOverview() {
|
||||
|
|
|
@ -14,7 +14,7 @@ import utils from "./utils.js";
|
|||
import importDialog from "../dialogs/import.js";
|
||||
|
||||
const $noteTabContentsContainer = $("#note-tab-container");
|
||||
const $savedIndicator = $("#saved-indicator");
|
||||
const $savedIndicator = $(".saved-indicator");
|
||||
|
||||
let noteChangeDisabled = false;
|
||||
|
||||
|
@ -118,6 +118,7 @@ function showTab(noteId) {
|
|||
|
||||
async function loadNoteDetail(noteId, newTab = false) {
|
||||
const loadedNote = await loadNote(noteId);
|
||||
let ctx;
|
||||
|
||||
if (noteContexts.length === 0 || newTab) {
|
||||
const tabContent = $("#note-tab-content-template").clone();
|
||||
|
@ -127,25 +128,28 @@ async function loadNoteDetail(noteId, newTab = false) {
|
|||
|
||||
$noteTabContentsContainer.append(tabContent);
|
||||
|
||||
noteContexts.push(new NoteContext(loadedNote));
|
||||
}
|
||||
// if it's a new tab explicitly by user then it's in background
|
||||
ctx = new NoteContext(loadedNote, newTab);
|
||||
noteContexts.push(ctx);
|
||||
|
||||
const ctx = getActiveContext();
|
||||
ctx.setNote(loadedNote);
|
||||
if (!newTab) {
|
||||
showTab(noteId);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx = getActiveContext();
|
||||
ctx.setNote(loadedNote);
|
||||
}
|
||||
|
||||
// we will try to render the new note only if it's still the active one in the tree
|
||||
// this is useful when user quickly switches notes (by e.g. holding down arrow) so that we don't
|
||||
// try to render all those loaded notes one after each other. This only guarantees that correct note
|
||||
// will be displayed independent of timing
|
||||
const currentTreeNode = treeService.getActiveNode();
|
||||
if (currentTreeNode && currentTreeNode.data.noteId !== loadedNote.noteId) {
|
||||
if (!newTab && currentTreeNode && currentTreeNode.data.noteId !== loadedNote.noteId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only now that we're in sync with tree active node we will switch activeNote
|
||||
ctx.note = loadedNote;
|
||||
ctx.noteId = loadedNote.noteId;
|
||||
|
||||
if (utils.isDesktop()) {
|
||||
// needs to happen after loading the note itself because it references active noteId
|
||||
// FIXME
|
||||
|
@ -159,8 +163,6 @@ async function loadNoteDetail(noteId, newTab = false) {
|
|||
|
||||
ctx.updateNoteView();
|
||||
|
||||
showTab(noteId);
|
||||
|
||||
noteChangeDisabled = true;
|
||||
|
||||
try {
|
||||
|
@ -202,13 +204,13 @@ async function loadNoteDetail(noteId, newTab = false) {
|
|||
|
||||
ctx.$scriptArea.empty();
|
||||
|
||||
await bundleService.executeRelationBundles(getActiveNote(), 'runOnNoteView');
|
||||
await bundleService.executeRelationBundles(ctx.note, 'runOnNoteView');
|
||||
|
||||
if (utils.isDesktop()) {
|
||||
await attributeService.showAttributes();
|
||||
|
||||
await ctx.showChildrenOverview();
|
||||
}
|
||||
// if (utils.isDesktop()) {
|
||||
// await attributeService.showAttributes();
|
||||
//
|
||||
// await ctx.showChildrenOverview();
|
||||
// }
|
||||
}
|
||||
|
||||
async function loadNote(noteId) {
|
||||
|
@ -271,6 +273,9 @@ $noteTabContentsContainer.on("drop", e => {
|
|||
});
|
||||
});
|
||||
|
||||
document.querySelector('.chrome-tabs')
|
||||
.addEventListener('activeTabChange', ({ detail }) => showTab(detail.tabEl.getAttribute('data-note-id')));
|
||||
|
||||
// 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
|
||||
$(window).on('beforeunload', () => { saveNotesIfChanged(); }); // don't convert to short form, handler doesn't like returned promise
|
||||
|
|
|
@ -8,6 +8,7 @@ class NoteDetailFile {
|
|||
* @param {NoteContext} ctx
|
||||
*/
|
||||
constructor(ctx) {
|
||||
this.ctx = ctx;
|
||||
this.$component = ctx.$noteTabContent.find('.note-detail-file');
|
||||
this.$fileNoteId = ctx.$noteTabContent.find(".file-note-id");
|
||||
this.$fileName = ctx.$noteTabContent.find(".file-filename");
|
||||
|
@ -33,33 +34,31 @@ class NoteDetailFile {
|
|||
}
|
||||
|
||||
async show() {
|
||||
const activeNote = noteDetailService.getActiveNote();
|
||||
|
||||
const attributes = await server.get('notes/' + activeNote.noteId + '/attributes');
|
||||
const attributes = await server.get('notes/' + this.ctx.note.noteId + '/attributes');
|
||||
const attributeMap = utils.toObject(attributes, l => [l.name, l.value]);
|
||||
|
||||
this.$component.show();
|
||||
|
||||
this.$fileNoteId.text(activeNote.noteId);
|
||||
this.$fileNoteId.text(this.ctx.note.noteId);
|
||||
this.$fileName.text(attributeMap.originalFileName || "?");
|
||||
this.$fileSize.text((attributeMap.fileSize || "?") + " bytes");
|
||||
this.$fileType.text(activeNote.mime);
|
||||
this.$fileType.text(this.ctx.note.mime);
|
||||
|
||||
if (activeNote.content) {
|
||||
if (this.ctx.note.content) {
|
||||
this.$previewRow.show();
|
||||
this.$previewContent.text(activeNote.content);
|
||||
this.$previewContent.text(this.ctx.note.content);
|
||||
}
|
||||
else {
|
||||
this.$previewRow.hide();
|
||||
}
|
||||
|
||||
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
||||
this.$openButton.toggle(!activeNote.isProtected);
|
||||
this.$openButton.toggle(!this.ctx.note.isProtected);
|
||||
}
|
||||
|
||||
getFileUrl() {
|
||||
// electron needs absolute URL so we extract current host, port, protocol
|
||||
return utils.getHost() + "/api/notes/" + noteDetailService.getActiveNoteId() + "/download";
|
||||
return utils.getHost() + "/api/notes/" + this.ctx.note.noteId + "/download";
|
||||
}
|
||||
|
||||
getContent() {}
|
||||
|
|
|
@ -714,10 +714,8 @@ div[data-notify="container"] {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
#saved-indicator {
|
||||
.saved-indicator {
|
||||
font-size: 150%;
|
||||
color: var(--main-text-color);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
#export-form .form-check {
|
||||
|
|
Loading…
Reference in a new issue