/* This file is part of Ezra Bible App.
Copyright (C) 2019 - 2023 Ezra Bible App Development Team <contact@ezrabibleapp.net>
Ezra Bible App is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Ezra Bible App is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Ezra Bible App. See the file LICENSE.
If not, see <http://www.gnu.org/licenses/>. */
const Mousetrap = require('mousetrap');
const Tab = require('../ui_models/tab.js');
const i18nHelper = require('../helpers/i18n_helper.js');
const { waitUntilIdle } = require('../helpers/ezra_helper.js');
const VerseBoxHelper = require('../helpers/verse_box_helper.js');
const verseListTitleHelper = require('../helpers/verse_list_title_helper.js');
const cacheController = require('./cache_controller.js');
const eventController = require('./event_controller.js');
const referenceVerseController = require('../controllers/reference_verse_controller.js');
const verseListController = require('../controllers/verse_list_controller.js');
/**
* The TabController manages the tab bar and the state of each tab.
*
* Like all other controllers it is only initialized once. It is accessible at the
* global object `app_controller.tab_controller`.
*
* @category Controller
*/
class TabController {
constructor() {
this.persistanceEnabled = false;
this.defaultLabel = "-------------";
this.tabTemplate = "<li><a href='#{href}'>#{label}</a> <span class='close-tab-button'><i class='fas fa-times'></i></span></li>";
this.nextTabId = 2;
/** @type Tab[] */
this.metaTabs = [];
this.loadingCompleted = false;
this.lastSelectedTabIndex = null;
this.verseBoxHelper = new VerseBoxHelper();
}
init(tabsElement, tabsPanelClass, addTabElement, tabHtmlTemplate, defaultBibleTranslationId) {
this.tabsElement = tabsElement;
this.tabsPanelClass = tabsPanelClass;
this.addTabElement = addTabElement;
this.tabHtmlTemplate = tabHtmlTemplate;
this.defaultBibleTranslationId = defaultBibleTranslationId;
this.initFirstTab();
var addTabShortCut = 'ctrl+t';
if (platformHelper.isMac()) {
addTabShortCut = 'command+t';
}
Mousetrap.bind(addTabShortCut, () => {
this.addTab();
return false;
});
this.initTabs();
eventController.subscribe('on-locale-changed', async () => {
this.localizeTemplate();
await this.updateTabTitlesAfterLocaleChange();
});
eventController.subscribePrioritized('on-translation-changed', async (data) => await this.onBibleTranslationChanged(data));
eventController.subscribe('on-translation-removed', async (translationId) => {
var installedTranslations = await app_controller.translation_controller.getInstalledModules();
this.onTranslationRemoved(translationId, installedTranslations);
});
eventController.subscribe('on-translation-added', (translationCode) => {
var currentBibleTranslationId = this.getTab().getBibleTranslationId();
if (currentBibleTranslationId == "" ||
currentBibleTranslationId == null) { // Update UI after a Bible translation becomes available
this.setCurrentBibleTranslationId(translationCode);
}
});
eventController.subscribe('on-all-translations-removed', async () => {
await this.reset();
});
// eslint-disable-next-line no-unused-vars
eventController.subscribe('on-tag-renamed', ({ tagId, oldTitle, newTitle }) => {
this.updateTabTitleAfterTagRenaming(oldTitle, newTitle);
});
eventController.subscribe('on-bible-text-loaded', () => {
let bibleTranslationId = this.getTab().getBibleTranslationId();
this.setCurrentBibleTranslationId(bibleTranslationId);
this.restoreScrollPosition();
if (this.persistanceEnabled) {
this.lastSelectedTabIndex = this.getSelectedTabIndex();
this.saveTabConfiguration();
}
});
eventController.subscribe('on-db-refresh', async () => {
verseListController.resetVerseListView();
await this.loadTabConfiguration(true);
});
}
initFirstTab() {
// Initialize the list with the first tab, which is there by default
var newTab = new Tab(this.defaultBibleTranslationId);
newTab.elementId = this.tabsElement + '-1';
this.metaTabs.push(newTab);
}
getTabCount() {
return this.metaTabs.length;
}
getTabHtml(tabIndex) {
var tabId = this.getSelectedTabId(tabIndex);
var tabElement = document.getElementById(tabId);
var html = tabElement.querySelector('.verse-list').innerHTML;
return html;
}
getReferenceVerseHtml(tabIndex) {
var tabId = this.getSelectedTabId(tabIndex);
var tabElement = document.getElementById(tabId);
var html = tabElement.querySelector('.reference-verse').innerHTML;
return html;
}
async saveTabConfiguration() {
//console.log('Saving tab configuration');
var savedMetaTabs = [];
for (var i = 0; i < this.metaTabs.length; i++) {
if (this.metaTabs[i].tab_search != null) {
this.metaTabs[i].tab_search.resetSearch();
}
var copiedMetaTab = Object.assign({}, this.metaTabs[i]);
copiedMetaTab.cachedText = this.getTabHtml(i);
copiedMetaTab.previousBook = null;
copiedMetaTab.headersLoaded = false;
if (copiedMetaTab.referenceVerseElementId != null) {
copiedMetaTab.cachedReferenceVerse = this.getReferenceVerseHtml(i);
} else {
copiedMetaTab.cachedReferenceVerse = null;
}
if (copiedMetaTab.tab_search != null) { // Each metaTab has a tab_search object.
// That object cannot be persisted, so we set it to null explicitly!
copiedMetaTab.tab_search = null;
}
savedMetaTabs.push(copiedMetaTab);
}
await cacheController.setCachedItem('tabConfiguration', savedMetaTabs);
}
updateFirstTabCloseButton() {
if (this.metaTabs.length > 1) {
this.showFirstTabCloseButton();
} else {
this.hideFirstTabCloseButton();
}
}
getFirstTabCloseButton() {
var firstTabCloseButton = $($('#' + this.tabsElement).find('.close-tab-button')[0]);
return firstTabCloseButton;
}
showFirstTabCloseButton() {
var firstTabCloseButton = this.getFirstTabCloseButton();
firstTabCloseButton.show();
}
hideFirstTabCloseButton() {
var firstTabCloseButton = this.getFirstTabCloseButton();
firstTabCloseButton.hide();
}
async loadMetaTabsFromSettings() {
let savedMetaTabs = await cacheController.getCachedItem('tabConfiguration', [], false);
let loadedTabCount = 0;
let tabCount = savedMetaTabs.length;
if (platformHelper.isMobile()) {
tabCount = 1;
}
for (let i = 0; i < tabCount; i++) {
var currentMetaTab = Tab.fromJsonObject(savedMetaTabs[i], i);
if (!currentMetaTab.isValid()) {
// We ignore the meta tab if it is invalid
continue;
}
console.log("Creating tab " + loadedTabCount + " from saved entry ... ");
currentMetaTab.selectCount = 1;
if (loadedTabCount == 0) {
currentMetaTab.elementId = this.metaTabs[0].elementId;
this.metaTabs[0] = currentMetaTab;
this.updateFirstTabCloseButton();
} else {
this.addTab(currentMetaTab, false);
}
var tabTitle = currentMetaTab.getTitle();
this.setTabTitle(tabTitle, currentMetaTab.getBibleTranslationId(), loadedTabCount);
await eventController.publishAsync('on-tab-added', i);
loadedTabCount += 1;
}
if (loadedTabCount > 0) {
console.log("Loaded " + loadedTabCount + " tabs from configuration!");
}
return loadedTabCount;
}
async populateFromMetaTabs(force=false) {
let cacheOutdated = await cacheController.isCacheOutdated();
let cacheInvalid = await cacheController.isCacheInvalid();
let tabCount = this.metaTabs.length;
if (cacheOutdated) {
console.log("Tab content cache is outdated. Database has been updated in the meantime!");
}
if (cacheInvalid) {
console.log("Cache is invalid. New app version?");
}
if (platformHelper.isMobile()) {
tabCount = 1;
}
for (let i = 0; i < tabCount; i++) {
let currentMetaTab = this.metaTabs[i];
if (cacheOutdated || cacheInvalid || force) {
currentMetaTab.cachedText = null;
currentMetaTab.cachedReferenceVerse = null;
}
let isSearch = (currentMetaTab.textType == 'search_results');
await app_controller.text_controller.prepareForNewText(true, isSearch, i);
if (currentMetaTab.textType == 'search_results') {
await app_controller.module_search_controller.populateSearchMenu(i);
let searchResultBookId = -1; // all books requested
if (app_controller.module_search_controller.searchResultsExceedPerformanceLimit(i)) {
searchResultBookId = 0; // no books requested - only list headers at first
}
await app_controller.module_search_controller.renderCurrentSearchResults(
searchResultBookId,
i,
undefined,
currentMetaTab.cachedText
);
} else {
const isInstantLoadingBook = await app_controller.translation_controller.isInstantLoadingBook(currentMetaTab.getBibleTranslationId(),
currentMetaTab.getBook());
await app_controller.text_controller.requestTextUpdate(
currentMetaTab.elementId,
currentMetaTab.book,
currentMetaTab.tagIdList,
currentMetaTab.cachedText,
currentMetaTab.cachedReferenceVerse,
null,
currentMetaTab.xrefs,
currentMetaTab.chapter,
isInstantLoadingBook,
i
);
}
}
}
async loadTabConfiguration(force=false) {
var bibleTranslationSettingAvailable = await ipcSettings.has('bibleTranslation');
if (bibleTranslationSettingAvailable) {
this.defaultBibleTranslationId = await ipcSettings.get('bibleTranslation');
}
var loadedTabCount = 0;
if (await cacheController.hasCachedItem('tabConfiguration')) {
uiHelper.showTextLoadingIndicator();
verseListController.showVerseListLoadingIndicator();
loadedTabCount = await this.loadMetaTabsFromSettings();
if (loadedTabCount > 0) {
await this.populateFromMetaTabs(force);
} else {
verseListController.hideVerseListLoadingIndicator();
uiHelper.hideTextLoadingIndicator();
}
}
// If no tabs are loaded from a previous session we need to explicitly invoke the on-tab-added event on the first tab
if (loadedTabCount == 0) {
eventController.publish('on-tab-added', 0);
}
// Give the UI some time to render
await waitUntilIdle();
// Call this method explicitly to initialize the first tab
await eventController.publishAsync('on-tab-selected', 0);
await waitUntilIdle();
this.loadingCompleted = true;
this.persistanceEnabled = true;
}
initTabs() {
this.tabs = $("#" + this.tabsElement).tabs();
this.updateFirstTabCloseButton();
var addTabText = i18n.t("bible-browser.open-new-tab");
var addTabButton = `<li><button id='add-tab-button' class='fg-button ui-corner-all ui-state-default' title='${addTabText}' i18n='[title]bible-browser.open-new-tab'><i class="fas fa-plus"></i></button></li>`;
$("#" + this.tabsElement).find('.ui-tabs-nav').append(addTabButton);
this.addTabElement = 'add-tab-button';
// eslint-disable-next-line no-unused-vars
$('#' + this.addTabElement).on("mousedown", (event) => {
setTimeout(() => {
$('#' + this.addTabElement).removeClass('ui-state-active');
}, 50);
this.addTab();
return false;
});
}
reloadTabs() {
this.tabs.tabs("destroy");
this.initTabs();
this.bindEvents();
}
getCorrectedIndex(ui) {
var index = ui.index;
// The ui.index may be higher as the actual available index. This happens after a tab was removed.
if (index > (this.getTabCount() - 1)) {
// In this case we simply adjust the index to the last available index.
index = this.getTabCount() - 1;
}
return index;
}
bindEvents() {
this.tabs.tabs({
select: (event, ui) => {
var index = this.getCorrectedIndex(ui);
var metaTab = this.getTab(index);
metaTab.selectCount += 1;
if (metaTab.addedInteractively || metaTab.selectCount > 1) { // We only run the on-tab-selected callbacks
// if the tab has been added interactively
// or after the initial select.
// This is necessary to ensure good visual performance when
// adding tabs automatically (like for finding all Strong's references).
index = this.getCorrectedIndex(ui);
ui.index = index;
if (metaTab.selectCount > 1) {
this.savePreviousTabScrollPosition();
}
if (metaTab.getTextType() != null) {
var currentVerseList = verseListController.getCurrentVerseList(index);
var currentVerseListHeader = verseListController.getCurrentVerseListHeader(index);
var currentReferenceVerse = referenceVerseController.getCurrentReferenceVerse(index);
currentVerseList.hide();
currentVerseListHeader.hide();
currentReferenceVerse.hide();
verseListController.showVerseListLoadingIndicator(index);
app_controller.verse_statistics_chart.resetChart(index);
}
this.lastSelectedTabIndex = index;
eventController.publish('on-tab-selected', ui.index);
}
},
show: (event, ui) => {
var index = this.getCorrectedIndex(ui);
var metaTab = this.getTab(index);
(async () => { // We use an async IIFE, because JQuery UI cannot deal with an async function
if (metaTab.addedInteractively || metaTab.selectCount > 1) { // see above
if (metaTab.getTextType() != null) {
await waitUntilIdle();
var index = this.getCorrectedIndex(ui);
var currentVerseList = verseListController.getCurrentVerseList(index);
var currentVerseListHeader = verseListController.getCurrentVerseListHeader(index);
var currentReferenceVerse = referenceVerseController.getCurrentReferenceVerse(index);
currentVerseList.show();
currentVerseListHeader.show();
currentReferenceVerse.show();
await app_controller.verse_statistics_chart.repaintChart(index);
verseListController.hideVerseListLoadingIndicator(index);
this.restoreScrollPosition(index);
}
}
})();
}
});
this.tabs.find('span.close-tab-button').unbind();
// Close icon: removing the tab on click
this.tabs.find('span.close-tab-button').on("mousedown", (event) => {
this.removeTab(event);
setTimeout(() => {
app_controller.book_selection_menu.highlightCurrentlySelectedBookInMenu();
}, 250);
});
uiHelper.configureButtonStyles('.ui-tabs-nav');
}
saveTabScrollPosition(tabIndex=undefined) {
var metaTab = this.getTab(tabIndex);
var firstVerseListAnchor = verseListController.getFirstVisibleVerseAnchor();
if (metaTab != null) {
if (firstVerseListAnchor != null) {
metaTab.setLocation(firstVerseListAnchor);
} else {
metaTab.setLocation("top");
}
}
}
savePreviousTabScrollPosition() {
if (this.lastSelectedTabIndex != null) {
this.saveTabScrollPosition(this.lastSelectedTabIndex);
}
}
restoreScrollPosition(tabIndex=undefined) {
var metaTab = this.getTab(tabIndex);
if (metaTab != null) {
var currentVerseListFrame = verseListController.getCurrentVerseListFrame(tabIndex);
if (currentVerseListFrame != null) {
const savedScrollTop = metaTab.getLocation();
if (savedScrollTop != null) {
// console.log("Setting location to " + savedScrollTop);
window.location = "#" + savedScrollTop;
}
}
}
}
getSelectedTabIndex() {
var selectedTabIndex = null;
if (this.tabs != null) {
selectedTabIndex = this.tabs.tabs("option").selected;
}
if (selectedTabIndex == null) {
selectedTabIndex = 0;
}
return selectedTabIndex;
}
getSelectedTabId(index = undefined) {
if (index === undefined) {
index = this.getSelectedTabIndex();
}
var allTabsPanels = document.getElementById(this.tabsElement).querySelectorAll('.' + this.tabsPanelClass);
var selectedTabsPanel = allTabsPanels[index];
var selectedTabsPanelId = "verse-list-tabs-1";
if (selectedTabsPanel != null) {
selectedTabsPanelId = selectedTabsPanel.getAttribute('id');
}
return selectedTabsPanelId;
}
addTab(metaTab = undefined, interactive = true, bibleTranslationId = undefined) {
var initialLoading = true;
if (metaTab === undefined) {
initialLoading = false;
if (bibleTranslationId != undefined) {
this.defaultBibleTranslationId = bibleTranslationId;
}
metaTab = new Tab(this.defaultBibleTranslationId, interactive);
}
metaTab.elementId = this.tabsElement + '-' + this.nextTabId;
this.metaTabs.push(metaTab);
var li = $(this.tabTemplate.replace(/#\{href\}/g, "#" + metaTab.elementId).replace(/#\{label\}/g, this.defaultLabel));
this.tabs.find(".ui-tabs-nav").find('li').last().remove();
this.tabs.find(".ui-tabs-nav").append(li);
this.tabs.append("<div id='" + metaTab.elementId + "' class='" + this.tabsPanelClass + "'>" + this.tabHtmlTemplate + "</div>");
if (interactive) {
this.lastSelectedTabIndex = this.getSelectedTabIndex();
this.savePreviousTabScrollPosition();
}
this.reloadTabs();
let newTabIndex = this.metaTabs.length - 1;
if (!initialLoading) {
this.tabs.tabs('select', newTabIndex);
}
this.nextTabId++;
this.updateFirstTabCloseButton();
if (!initialLoading) {
eventController.publish('on-tab-added', newTabIndex);
}
}
removeTab(event) {
var href = $(event.target).closest("li").find('a').attr('href');
var all_tabs = $(event.target).closest("ul").find("li");
for (var i = 0; i < all_tabs.length; i++) {
var current_href = $(all_tabs[i]).find('a').attr('href');
if (current_href == href) {
this.metaTabs.splice(i, 1);
this.tabs.tabs("remove", i);
break;
}
}
this.updateFirstTabCloseButton();
this.saveTabConfiguration();
}
removeAllExtraTabs() {
var all_tabs = this.tabs.find("li");
for (var i = 2; // We only go down to 2, because that's the initial amount of list elements (first tab + add tab button)
i < all_tabs.length;
i++) {
this.metaTabs.pop();
this.tabs.tabs("remove", 1);
}
}
/**
* Resets the state of TabController to the initial state (corresponds to the state right after first installation)
*/
async reset() {
this.removeAllExtraTabs();
this.setCurrentBibleTranslationId(null);
const tab = this.getTab();
if (tab != null) {
tab.setTagIdList("");
tab.setXrefs(null);
tab.setReferenceVerseElementId(null);
}
this.setCurrentTabBook(null, "", "", null);
this.resetCurrentTabTitle();
if (this.persistanceEnabled) {
await cacheController.deleteCache('tabConfiguration');
}
}
/**
* @param {Number} index The tab index of the requested Tab
* @returns @type Tab
*/
getTab(index = undefined) {
if (index === undefined) {
index = this.getSelectedTabIndex();
}
if (index >= this.metaTabs.length) {
index = this.metaTabs.length - 1;
}
return this.metaTabs[index];
}
getTabById(tabId) {
for (var i = 0; i < this.metaTabs.length; i++) {
var currentTabId = this.getSelectedTabId(i);
if (currentTabId == tabId) {
return this.metaTabs[i];
}
}
return null;
}
resetCurrentTabTitle() {
if (platformHelper.isMobile()) {
this.setTabTitle('');
} else {
this.setTabTitle(this.defaultLabel);
}
}
setTabTitle(title, bibleTranslationId = undefined, index = undefined) {
if (index === undefined) {
index = this.getSelectedTabIndex();
}
var tabsElement = $('#' + this.tabsElement);
var tab = $(tabsElement.find('li')[index]);
var link = $(tab.find('a')[0]);
var tabTitle = title;
if (bibleTranslationId !== undefined) {
tabTitle += ' [' + bibleTranslationId + ']';
}
var currentTitle = link.html();
if (tabTitle != currentTitle) {
link.html(tabTitle);
}
var currentTabTitleLabel = tabsElement.find('.current-tab-title-label');
currentTabTitleLabel.html(title);
}
getTabTitle() {
var index = this.getSelectedTabIndex();
var tabsElement = $('#' + this.tabsElement);
var tab = $(tabsElement.find('li')[index]);
var link = $(tab.find('a')[0]);
var linkText = link.html().split(" ");
linkText.pop();
return linkText.join(" ");
}
refreshBibleTranslationInTabTitle(bibleTranslationId) {
var currentTabTitle = this.getTabTitle();
this.setTabTitle(currentTabTitle, bibleTranslationId);
}
setCurrentTabBook(bookCode, bookTitle, referenceBookTitle, chapter=undefined) {
const tab = this.getTab();
if (tab != null) {
tab.setBook(bookCode, bookTitle, referenceBookTitle, chapter);
var currentTranslationId = tab.getBibleTranslationId();
if (bookTitle != undefined && bookTitle != null) {
this.setTabTitle(bookTitle, currentTranslationId);
}
}
}
setCurrentTagTitleList(tagTitleList, verseReference, index = undefined) {
this.getTab(index).setTagTitleList(tagTitleList);
var currentTranslationId = this.getTab(index).getBibleTranslationId();
tagTitleList = verseListTitleHelper.shortenTitleList(tagTitleList);
if (tagTitleList != undefined && tagTitleList != null) {
if (tagTitleList == "") {
this.resetCurrentTabTitle();
} else {
var tagTitle = "";
if (verseReference != null) tagTitle += verseReference + " – ";
if (platformHelper.isElectron()) {
tagTitle += i18n.t('tags.verses-tagged-with') + " ";
}
tagTitle += "<i>" + tagTitleList + "</i>";
this.setTabTitle(tagTitle, currentTranslationId, index);
this.getTab(index).setTaggedVersesTitle(tagTitle);
}
}
}
setCurrentTabXrefTitle(xrefTitle, index = undefined) {
this.getTab(index).setXrefTitle(xrefTitle);
var currentTranslationId = this.getTab(index).getBibleTranslationId();
if (xrefTitle != undefined && xrefTitle != null) {
if (xrefTitle == "") {
this.resetCurrentTabTitle();
} else {
this.setTabTitle(xrefTitle, currentTranslationId, index);
}
}
}
setTabSearch(searchTerm, index = undefined) {
this.getTab(index).setSearchTerm(searchTerm);
const showSearchResultsInPopup = app_controller.optionsMenu._showSearchResultsInPopupOption.isChecked;
if (!showSearchResultsInPopup) {
var currentTranslationId = this.getTab(index).getBibleTranslationId();
if (searchTerm != undefined && searchTerm != null) {
var searchTabTitle = this.getSearchTabTitle(searchTerm);
this.setTabTitle(searchTabTitle, currentTranslationId, index);
}
}
}
getSearchTabTitle(searchTerm) {
return i18n.t("menu.search") + ": " + searchTerm;
}
setLastHighlightedNavElementIndex(index, isHeaderNav = false) {
var currentTabIndex = this.getSelectedTabIndex();
if (isHeaderNav) {
this.metaTabs[currentTabIndex].lastHighlightedHeaderIndex = index;
} else {
this.metaTabs[currentTabIndex].lastHighlightedChapterIndex = index;
}
}
getLastHighlightedNavElementIndex(isHeaderNav = false) {
var currentTabIndex = this.getSelectedTabIndex();
if (isHeaderNav) {
return this.metaTabs[currentTabIndex].lastHighlightedHeaderIndex;
} else {
return this.metaTabs[currentTabIndex].lastHighlightedChapterIndex;
}
}
clearLastHighlightedNavElementIndex() {
var currentTabIndex = this.getSelectedTabIndex();
this.metaTabs[currentTabIndex].lastHighlightedHeaderIndex = null;
this.metaTabs[currentTabIndex].lastHighlightedChapterIndex = null;
}
setCurrentBibleTranslationId(bibleTranslationId) {
const tab = this.getTab();
if (tab != null) {
tab.setBibleTranslationId(bibleTranslationId);
}
if (bibleTranslationId != null) {
this.defaultBibleTranslationId = bibleTranslationId;
app_controller.info_popup.enableCurrentAppInfoButton();
}
}
async getCurrentBibleTranslationName() {
var module = await ipcNsi.getLocalModule(this.getTab().getBibleTranslationId());
return module.description;
}
isCurrentTabEmpty() {
var currentTabIndex = this.getSelectedTabIndex();
var currentTab = this.metaTabs[currentTabIndex];
return currentTab.book == null && currentTab.tagIdList == "" && currentTab.xrefs == null;
}
isCurrentTab(tabIndex) {
var selectedTabIndex = this.getSelectedTabIndex();
return (tabIndex == selectedTabIndex);
}
async updateTabTitleAfterTagRenaming(old_title, new_title) {
for (var i = 0; i < this.metaTabs.length; i++) {
var currentMetaTab = this.metaTabs[i];
if (currentMetaTab.getTextType() == 'tagged_verses') {
var currentTagTitleList = currentMetaTab.tagTitleList;
var tag_list = currentTagTitleList.split(', ');
for (var j = 0; j < tag_list.length; j++) {
var current_tag = tag_list[j];
if (current_tag == old_title) {
tag_list[j] = new_title;
break;
}
}
currentMetaTab.setTagTitleList(tag_list.join(', '));
var tagTitle = "";
var referenceVerseElement = document.querySelector('.' + currentMetaTab.getReferenceVerseElementId());
if (referenceVerseElement != null) {
var localizedReference = await this.verseBoxHelper.getLocalizedVerseReference(referenceVerseElement);
if (localizedReference != null) tagTitle += localizedReference + " – ";
}
if (platformHelper.isElectron()) {
tagTitle += i18n.t('tags.verses-tagged-with') + " ";
}
tagTitle += "<i>" + tag_list.join(', ') + "</i>";
this.setTabTitle(tagTitle, currentMetaTab.getBibleTranslationId(), i);
currentMetaTab.setTaggedVersesTitle(tagTitle);
}
}
}
async updateTabTitlesAfterLocaleChange() {
for (let i = 0; i < this.metaTabs.length; i++) {
const currentMetaTab = this.metaTabs[i];
switch (currentMetaTab.getTextType()) {
case 'book': {
let referenceBookTitle = currentMetaTab.getReferenceBookTitle();
if (referenceBookTitle != null) {
currentMetaTab.bookTitle = await i18nHelper.getSwordTranslation(currentMetaTab.getReferenceBookTitle());
const tabTitle = currentMetaTab.bookTitle;
this.setTabTitle(tabTitle, currentMetaTab.getBibleTranslationId(), i);
}
}
break;
case 'search_results': {
const tabTitle = this.getSearchTabTitle(currentMetaTab.getSearchTerm());
this.setTabTitle(tabTitle, currentMetaTab.getBibleTranslationId(), i);
}
break;
case 'tagged_verses': {
let localizedReference = null;
if (currentMetaTab.getReferenceVerseElementId() != null) {
localizedReference = await referenceVerseController.getLocalizedReferenceVerse(i);
}
this.setCurrentTagTitleList(currentMetaTab.tagTitleList, localizedReference, i);
}
break;
case 'xrefs': {
const localizedReference = await referenceVerseController.getLocalizedReferenceVerse(i);
const tabTitle = verseListTitleHelper.getXrefsVerseListTitle(localizedReference);
this.setCurrentTabXrefTitle(tabTitle, i);
}
break;
}
}
}
async onBibleTranslationChanged({ from: oldBibleTranslationId, to: newBibleTranslationId }) {
var currentTab = this.getTab();
this.setCurrentBibleTranslationId(newBibleTranslationId);
this.refreshBibleTranslationInTabTitle(newBibleTranslationId);
// The tab search is not valid anymore if the translation is changing. Therefore we reset it.
if (currentTab.tab_search != null) {
currentTab.tab_search.resetSearch();
}
var isInstantLoadingBook = true;
if (currentTab.getTextType() == 'book') {
// We set the previous book to the current book. This will be used in NavigationPane to avoid reloading the chapter list.
currentTab.setPreviousBook(currentTab.getBook());
isInstantLoadingBook = await app_controller.translation_controller.isInstantLoadingBook(newBibleTranslationId, currentTab.getBook());
}
if (currentTab.getTextType() == 'search_results') {
await app_controller.text_controller.prepareForNewText(true, true);
app_controller.module_search_controller.startSearch(null, this.getSelectedTabIndex(), currentTab.getSearchTerm());
} else {
if (!this.isCurrentTabEmpty()) {
this.saveTabScrollPosition();
await app_controller.text_controller.prepareForNewText(false, false);
await app_controller.text_controller.requestTextUpdate(
this.getSelectedTabId(),
currentTab.getBook(),
currentTab.getTagIdList(),
null,
null,
null,
currentTab.getXrefs(),
currentTab.getChapter(),
isInstantLoadingBook
);
if (currentTab.getReferenceVerseElementId() != null) {
await referenceVerseController.updateReferenceVerseTranslation(oldBibleTranslationId, newBibleTranslationId);
}
if (currentTab.getTextType() == 'book') {
app_controller.tag_statistics.highlightFrequentlyUsedTags();
}
}
}
}
onTranslationRemoved(translationId, translationList) {
if (translationId == this.defaultBibleTranslationId) {
if (translationList.length > 0) {
this.defaultBibleTranslationId = translationList[0];
} else {
this.defaultBibleTranslationId = null;
}
}
}
/**
* Function to update locale strings in new tab template
* Called on locale change
*/
localizeTemplate() {
let $tabHtmlTemplate = $('<div>').append(this.tabHtmlTemplate);
$tabHtmlTemplate.localize();
this.tabHtmlTemplate = $tabHtmlTemplate.html();
}
}
module.exports = TabController;
Source