basic opening and switching tabs

This commit is contained in:
zadam 2019-05-03 21:50:14 +02:00
parent c7b5784123
commit 39093cbc4c
6 changed files with 44 additions and 39 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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() {

View file

@ -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

View file

@ -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() {}

View file

@ -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 {