mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 15:11:31 +08:00 
			
		
		
		
	basic opening and switching tabs
This commit is contained in:
		
							parent
							
								
									c7b5784123
								
							
						
					
					
						commit
						39093cbc4c
					
				@ -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();
 | 
			
		||||
        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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user