refactored tab activation

This commit is contained in:
zadam 2020-01-19 21:12:53 +01:00
parent 1098d75ce0
commit 0760dc742b
8 changed files with 79 additions and 44 deletions

View File

@ -30,6 +30,7 @@ import ProtectedNoteSwitchWidget from "../widgets/protected_note_switch.js";
import NoteTypeWidget from "../widgets/note_type.js"; import NoteTypeWidget from "../widgets/note_type.js";
import NoteActionsWidget from "../widgets/note_actions.js"; import NoteActionsWidget from "../widgets/note_actions.js";
import protectedSessionHolder from "./protected_session_holder.js"; import protectedSessionHolder from "./protected_session_holder.js";
import bundleService from "./bundle.js";
class AppContext { class AppContext {
constructor() { constructor() {
@ -39,6 +40,7 @@ class AppContext {
this.tabsChangedTaskId = null; this.tabsChangedTaskId = null;
/** @type {TabRowWidget} */ /** @type {TabRowWidget} */
this.tabRow = null; this.tabRow = null;
this.activeTabId = null;
} }
showWidgets() { showWidgets() {
@ -180,9 +182,7 @@ class AppContext {
/** @returns {TabContext} */ /** @returns {TabContext} */
getActiveTabContext() { getActiveTabContext() {
const tabId = this.tabRow.activeTabId; return this.tabContexts.find(tc => tc.tabId === this.activeTabId);
return this.tabContexts.find(tc => tc.tabId === tabId);
} }
/** @returns {string|null} */ /** @returns {string|null} */
@ -268,10 +268,10 @@ class AppContext {
} }
async openEmptyTab() { async openEmptyTab() {
const ctx = new TabContext(this, this.tabRow); const tabContext = new TabContext(this, this.tabRow);
this.tabContexts.push(ctx); this.tabContexts.push(tabContext);
await this.tabRow.activateTab(ctx.$tab[0]); await this.activateTab(tabContext.tabId);
} }
async filterTabs(noteId) { async filterTabs(noteId) {
@ -291,8 +291,7 @@ class AppContext {
async saveOpenTabs() { async saveOpenTabs() {
const openTabs = []; const openTabs = [];
for (const tabEl of this.tabRow.tabEls) { for (const tabId of this.tabRow.getTabIdsInOrder()) {
const tabId = tabEl.getAttribute('data-tab-id');
const tabContext = appContext.getTabContexts().find(tc => tc.tabId === tabId); const tabContext = appContext.getTabContexts().find(tc => tc.tabId === tabId);
if (tabContext) { if (tabContext) {
@ -324,23 +323,42 @@ class AppContext {
this.tabsChangedTaskId = setTimeout(() => this.saveOpenTabs(), 1000); this.tabsChangedTaskId = setTimeout(() => this.saveOpenTabs(), 1000);
} }
async activateTab(tabContext) { async activateTab(tabId) {
return this.tabRow.activateTab(tabContext.$tab[0]); this.activeTabId = tabId;
this.trigger('activeTabChanged', { tabId: this.activeTabId });
} }
newTabListener() { newTabListener() {
this.openEmptyTab(); this.openEmptyTab();
} }
async tabRemoveListener({tabId}) { async removeTab(tabId) {
this.tabContexts.filter(nc => nc.tabId === tabId) const tabContextToRemove = this.tabContexts.find(tc => tc.tabId === tabId);
.forEach(tc => tc.remove()); const tabIdsInOrder = this.tabRow.getTabIdsInOrder();
this.tabContexts = this.tabContexts.filter(nc => nc.tabId !== tabId); if (!tabContextToRemove) {
return;
}
if (this.tabContexts.length === 0) { if (this.tabContexts.length === 0) {
this.openEmptyTab(); this.openEmptyTab();
} }
else {
const oldIdx = tabIdsInOrder.findIndex(tid => tid === tabId);
const newActiveTabId = tabIdsInOrder[oldIdx === tabIdsInOrder.length ? oldIdx - 1 : oldIdx + 1];
if (newActiveTabId) {
this.activateTab(newActiveTabId);
}
else {
console.log("Failed to find next tabcontext to activate");
}
}
await tabContextToRemove.remove();
this.tabContexts = this.tabContexts.filter(tc => tc.tabId === tabId);
this.openTabsChanged(); this.openTabsChanged();
} }
@ -359,6 +377,9 @@ class AppContext {
if (activeTabContext.note.isProtected && protectedSessionHolder.isProtectedSessionAvailable()) { if (activeTabContext.note.isProtected && protectedSessionHolder.isProtectedSessionAvailable()) {
protectedSessionHolder.touchProtectedSession(); protectedSessionHolder.touchProtectedSession();
} }
// run async
bundleService.executeRelationBundles(activeTabContext.note, 'runOnNoteChange', activeTabContext);
} }
} }
@ -378,6 +399,7 @@ keyboardActionService.setGlobalActionHandler('ActivateNextTab', () => {
const nextTab = this.tabRow.nextTabEl; const nextTab = this.tabRow.nextTabEl;
if (nextTab) { if (nextTab) {
// FIXME
this.tabRow.activateTab(nextTab); this.tabRow.activateTab(nextTab);
} }
}); });
@ -386,6 +408,7 @@ keyboardActionService.setGlobalActionHandler('ActivatePreviousTab', () => {
const prevTab = this.tabRow.previousTabEl; const prevTab = this.tabRow.previousTabEl;
if (prevTab) { if (prevTab) {
// FIXME
this.tabRow.activateTab(prevTab); this.tabRow.activateTab(prevTab);
} }
}); });

View File

@ -113,7 +113,7 @@ async function loadNoteDetail(origNotePath, options = {}) {
const loadPromise = loadNoteDetailToContext(ctx, notePath).then(() => { const loadPromise = loadNoteDetailToContext(ctx, notePath).then(() => {
if (activate) { if (activate) {
return appContext.activateTab(ctx); return appContext.activateTab(ctx.tabId);
} }
else { else {
return Promise.resolve(); return Promise.resolve();

View File

@ -81,6 +81,12 @@ class TabContext extends Component {
return this.tabId === this.tabRow.activeTabId; return this.tabId === this.tabRow.activeTabId;
} }
async remove() {
await this.trigger('beforeTabRemove', {tabId: this.tabId}, true);
this.trigger('tabRemoved', {tabId: this.tabId});
}
setupClasses() { setupClasses() {
for (const clazz of Array.from(this.$tab[0].classList)) { // create copy to safely iterate over while removing classes for (const clazz of Array.from(this.$tab[0].classList)) { // create copy to safely iterate over while removing classes
if (clazz !== 'note-tab') { if (clazz !== 'note-tab') {
@ -123,8 +129,7 @@ class TabContext extends Component {
// FIXME trigger "noteSaved" event so that title indicator is triggered // FIXME trigger "noteSaved" event so that title indicator is triggered
this.eventReceived('noteSaved'); this.eventReceived('noteSaved');
// run async
bundleService.executeRelationBundles(this.note, 'runOnNoteChange', this);
} }
async saveNoteIfChanged() { async saveNoteIfChanged() {

View File

@ -18,6 +18,12 @@ class BasicWidget extends Component {
this.$widget.toggle(show); this.$widget.toggle(show);
} }
remove() {
if (this.$widget) {
this.$widget.remove();
}
}
cleanup() {} cleanup() {}
} }

View File

@ -132,7 +132,13 @@ export default class NoteTitleWidget extends TabAwareWidget {
} }
} }
async beforeNoteSwitch({tabId}) { async beforeNoteSwitchListener({tabId}) {
if (this.isTab(tabId)) {
await this.spacedUpdate.updateNowIfNecessary();
}
}
async beforeTabRemoveListener({tabId}) {
if (this.isTab(tabId)) { if (this.isTab(tabId)) {
await this.spacedUpdate.updateNowIfNecessary(); await this.spacedUpdate.updateNowIfNecessary();
} }

View File

@ -408,6 +408,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
if (oldActiveNode) { if (oldActiveNode) {
oldActiveNode.setActive(false); oldActiveNode.setActive(false);
oldActiveNode.setFocus(false);
} }
if (this.tabContext && this.tabContext.notePath) { if (this.tabContext && this.tabContext.notePath) {

View File

@ -35,6 +35,14 @@ export default class TabCachingWidget extends TabAwareWidget {
return false; // stop propagation to children return false; // stop propagation to children
} }
tabRemovedListener({tabId}) {
const widget = this.widgets[tabId];
if (widget) {
widget.remove();
}
}
toggle(show) { toggle(show) {
for (const tabId in this.widgets) { for (const tabId in this.widgets) {
this.widgets[tabId].toggle(show && this.tabContext && tabId === this.tabContext.tabId); this.widgets[tabId].toggle(show && this.tabContext && tabId === this.tabContext.tabId);

View File

@ -399,11 +399,11 @@ export default class TabRowWidget extends BasicWidget {
setTabCloseEventListener(tabEl) { setTabCloseEventListener(tabEl) {
tabEl.querySelector('.note-tab-close') tabEl.querySelector('.note-tab-close')
.addEventListener('click', _ => this.removeTab(tabEl.getAttribute('data-tab-id'))); .addEventListener('click', _ => this.appContext.removeTab(tabEl.getAttribute('data-tab-id')));
tabEl.addEventListener('mousedown', e => { tabEl.addEventListener('mousedown', e => {
if (e.which === 2) { if (e.which === 2) {
this.removeTab(tabEl.getAttribute('data-tab-id')); this.appContext.removeTab(tabEl.getAttribute('data-tab-id'));
return true; // event has been handled return true; // event has been handled
} }
@ -464,44 +464,26 @@ export default class TabRowWidget extends BasicWidget {
return !!this.activeTabEl; return !!this.activeTabEl;
} }
activateTab(tabEl) { activeTabChangedListener({tabId}) {
const tabEl = this.getTabById(tabId)[0];
const activeTabEl = this.activeTabEl; const activeTabEl = this.activeTabEl;
if (activeTabEl === tabEl) return; if (activeTabEl === tabEl) return;
if (activeTabEl) activeTabEl.removeAttribute('active'); if (activeTabEl) activeTabEl.removeAttribute('active');
tabEl.setAttribute('active', ''); tabEl.setAttribute('active', '');
this.trigger('activeTabChanged', { tabId: tabEl.getAttribute('data-tab-id') });
} }
removeTab(tabId) { removeTab(tabId) {
const tabEl = this.$widget.find(`[data-tab-id='${tabId}']`)[0]; const tabEl = this.getTabById(tabId)[0];
if (tabEl === this.activeTabEl) {
if (tabEl.nextElementSibling && tabEl.nextElementSibling.classList.contains("note-tab")) {
this.activateTab(tabEl.nextElementSibling)
} else if (tabEl.previousElementSibling && tabEl.previousElementSibling.classList.contains("note-tab")) {
this.activateTab(tabEl.previousElementSibling)
}
}
tabEl.parentNode.removeChild(tabEl); tabEl.parentNode.removeChild(tabEl);
this.trigger('tabRemove', { tabId: tabEl.getAttribute('data-tab-id') });
this.cleanUpPreviouslyDraggedTabs(); this.cleanUpPreviouslyDraggedTabs();
this.layoutTabs(); this.layoutTabs();
this.setupDraggabilly(); this.setupDraggabilly();
this.setVisibility(); this.setVisibility();
} }
removeAllTabs() { getTabIdsInOrder() {
for (const tabEl of this.tabEls) { return this.tabEls.map(el => el.getAttribute('data-tab-id'));
this.removeTab(tabEl.getAttribute('data-tab-id'));
}
}
removeAllTabsExceptForThis(remainingTabEl) {
for (const tabEl of this.tabEls) {
if (remainingTabEl !== tabEl) {
this.removeTab(tabEl.getAttribute('data-tab-id'));
}
}
} }
updateTab(tabEl, tabProperties) { updateTab(tabEl, tabProperties) {
@ -519,6 +501,10 @@ export default class TabRowWidget extends BasicWidget {
.forEach($el => $el.find('.note-tab-title').text(title)); .forEach($el => $el.find('.note-tab-title').text(title));
} }
tabRemovedListener({tabId}) {
this.removeTab(tabId);
}
cleanUpPreviouslyDraggedTabs() { cleanUpPreviouslyDraggedTabs() {
this.tabEls.forEach((tabEl) => tabEl.classList.remove('note-tab-was-just-dragged')); this.tabEls.forEach((tabEl) => tabEl.classList.remove('note-tab-was-just-dragged'));
} }
@ -552,7 +538,7 @@ export default class TabRowWidget extends BasicWidget {
this.draggabillies.push(draggabilly); this.draggabillies.push(draggabilly);
draggabilly.on('pointerDown', _ => { draggabilly.on('pointerDown', _ => {
this.activateTab(tabEl) this.appContext.activateTab(tabEl.getAttribute('data-tab-id'));
}); });
draggabilly.on('dragStart', _ => { draggabilly.on('dragStart', _ => {