From 39093cbc4c2df1c198e4f27c72c0dbacb4fd08ec Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 3 May 2019 21:50:14 +0200 Subject: [PATCH] basic opening and switching tabs --- src/public/javascripts/services/attributes.js | 2 +- .../javascripts/services/context_menu.js | 2 + .../javascripts/services/note_context.js | 17 ++++---- .../javascripts/services/note_detail.js | 41 +++++++++++-------- .../javascripts/services/note_detail_file.js | 17 ++++---- src/public/stylesheets/style.css | 4 +- 6 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/public/javascripts/services/attributes.js b/src/public/javascripts/services/attributes.js index cb7f7a50d..1643c0d49 100644 --- a/src/public/javascripts/services/attributes.js +++ b/src/public/javascripts/services/attributes.js @@ -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; diff --git a/src/public/javascripts/services/context_menu.js b/src/public/javascripts/services/context_menu.js index 17f09590a..74f31d6f4 100644 --- a/src/public/javascripts/services/context_menu.js +++ b/src/public/javascripts/services/context_menu.js @@ -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; diff --git a/src/public/javascripts/services/note_context.js b/src/public/javascripts/services/note_context.js index eba3294ad..8562152b5 100644 --- a/src/public/javascripts/services/note_context.js +++ b/src/public/javascripts/services/note_context.js @@ -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() { diff --git a/src/public/javascripts/services/note_detail.js b/src/public/javascripts/services/note_detail.js index aba0b62bc..bfec00715 100644 --- a/src/public/javascripts/services/note_detail.js +++ b/src/public/javascripts/services/note_detail.js @@ -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 diff --git a/src/public/javascripts/services/note_detail_file.js b/src/public/javascripts/services/note_detail_file.js index 98319f522..ff143da0a 100644 --- a/src/public/javascripts/services/note_detail_file.js +++ b/src/public/javascripts/services/note_detail_file.js @@ -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() {} diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index 082128dfd..cc56ce891 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -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 {