MOBILE-3063 reading-mode: Find header in splitview if needed
parent
e6733bbd65
commit
170817ed7c
|
@ -89,7 +89,7 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
|
||||||
*/
|
*/
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const header = await this.searchHeader();
|
const header = await CoreDom.findIonHeaderFromElement(this.element);
|
||||||
if (header) {
|
if (header) {
|
||||||
// Search the right buttons container (start, end or any).
|
// Search the right buttons container (start, end or any).
|
||||||
let selector = 'ion-buttons';
|
let selector = 'ion-buttons';
|
||||||
|
@ -192,43 +192,6 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
|
||||||
return componentRef.instance;
|
return componentRef.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Search the ion-header where the buttons should be added.
|
|
||||||
*
|
|
||||||
* @returns Promise resolved with the header element.
|
|
||||||
*/
|
|
||||||
protected async searchHeader(): Promise<HTMLIonHeaderElement> {
|
|
||||||
await CoreDom.waitToBeInDOM(this.element);
|
|
||||||
let parentPage: HTMLElement | null = this.element;
|
|
||||||
|
|
||||||
while (parentPage && parentPage.parentElement) {
|
|
||||||
const content = parentPage.closest<HTMLIonContentElement>('ion-content');
|
|
||||||
if (content) {
|
|
||||||
// Sometimes ion-page class is not yet added by the ViewController, wait for content to render.
|
|
||||||
await content.componentOnReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
parentPage = parentPage.parentElement.closest('.ion-page, .ion-page-hidden, .ion-page-invisible');
|
|
||||||
|
|
||||||
// Check if the page has a header. If it doesn't, search the next parent page.
|
|
||||||
let header = parentPage?.querySelector<HTMLIonHeaderElement>(':scope > ion-header');
|
|
||||||
|
|
||||||
if (header && getComputedStyle(header).display !== 'none') {
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find using content if any.
|
|
||||||
header = content?.parentElement?.querySelector<HTMLIonHeaderElement>(':scope > ion-header');
|
|
||||||
|
|
||||||
if (header && getComputedStyle(header).display !== 'none') {
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header not found, reject.
|
|
||||||
throw Error('Header not found.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show or hide all the elements.
|
* Show or hide all the elements.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -47,7 +47,6 @@ export class CoreReadingModeDirective implements AfterViewInit, OnDestroy {
|
||||||
protected hiddenElements: HTMLElement[] = [];
|
protected hiddenElements: HTMLElement[] = [];
|
||||||
protected renamedStyles: HTMLElement[] = [];
|
protected renamedStyles: HTMLElement[] = [];
|
||||||
protected enabled = false;
|
protected enabled = false;
|
||||||
protected contentEl?: HTMLIonContentElement;
|
|
||||||
protected header?: CoreCollapsibleHeaderDirective;
|
protected header?: CoreCollapsibleHeaderDirective;
|
||||||
protected logger = CoreLogger.getInstance('CoreReadingModeDirective');
|
protected logger = CoreLogger.getInstance('CoreReadingModeDirective');
|
||||||
|
|
||||||
|
@ -64,7 +63,12 @@ export class CoreReadingModeDirective implements AfterViewInit, OnDestroy {
|
||||||
async ngAfterViewInit(): Promise<void> {
|
async ngAfterViewInit(): Promise<void> {
|
||||||
await this.viewportPromise;
|
await this.viewportPromise;
|
||||||
await CoreWait.nextTick();
|
await CoreWait.nextTick();
|
||||||
this.addTextViewerButton();
|
await this.addTextViewerButton();
|
||||||
|
|
||||||
|
this.enabled = document.body.classList.contains('core-reading-mode-enabled');
|
||||||
|
if (this.enabled) {
|
||||||
|
await this.enterReadingMode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,24 +76,26 @@ export class CoreReadingModeDirective implements AfterViewInit, OnDestroy {
|
||||||
*/
|
*/
|
||||||
protected async addTextViewerButton(): Promise<void> {
|
protected async addTextViewerButton(): Promise<void> {
|
||||||
const page = CoreDom.closest(this.element, '.ion-page');
|
const page = CoreDom.closest(this.element, '.ion-page');
|
||||||
this.contentEl = page?.querySelector('ion-content') ?? undefined;
|
const contentEl = page?.querySelector('ion-content') ?? undefined;
|
||||||
|
|
||||||
const buttonsContainer = page?.querySelector<HTMLIonButtonsElement>('ion-header ion-toolbar ion-buttons[slot="end"]');
|
const header = await CoreDom.findIonHeaderFromElement(this.element);
|
||||||
|
const buttonsContainer = header?.querySelector<HTMLIonButtonsElement>('ion-toolbar ion-buttons[slot="end"]');
|
||||||
if (!buttonsContainer) {
|
if (!buttonsContainer || !contentEl) {
|
||||||
this.logger.warn('The header was not found, or it didn\'t have any ion-buttons on slot end.');
|
this.logger.warn('The header was not found, or it didn\'t have any ion-buttons on slot end.');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contentEl.classList.add('core-reading-mode-content');
|
||||||
|
|
||||||
if (buttonsContainer.querySelector('.core-text-viewer-button')) {
|
if (buttonsContainer.querySelector('.core-text-viewer-button')) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.contentEl?.classList.add('core-reading-mode-content');
|
const collapsibleHeader = CoreDirectivesRegistry.resolve(header, CoreCollapsibleHeaderDirective);
|
||||||
|
if (collapsibleHeader) {
|
||||||
const header = CoreDirectivesRegistry.resolve(page?.querySelector('ion-header'), CoreCollapsibleHeaderDirective);
|
this.header = collapsibleHeader;
|
||||||
if (header) {
|
|
||||||
this.header = header;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const label = Translate.instant('core.viewer.enterreadingmode');
|
const label = Translate.instant('core.viewer.enterreadingmode');
|
||||||
|
@ -118,7 +124,6 @@ export class CoreReadingModeDirective implements AfterViewInit, OnDestroy {
|
||||||
} else {
|
} else {
|
||||||
this.showReadingSettings();
|
this.showReadingSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,8 +219,14 @@ export class CoreReadingModeDirective implements AfterViewInit, OnDestroy {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.disableReadingMode();
|
|
||||||
this.viewportPromise?.cancel();
|
this.viewportPromise?.cancel();
|
||||||
|
|
||||||
|
if (this.enabled && document.body.querySelectorAll('[core-reading-mode]')) {
|
||||||
|
// Do not disable if there are more instances of the directive in the DOM.
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.disableReadingMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -781,6 +781,44 @@ export class CoreDom {
|
||||||
return !!units && units.length > 1;
|
return !!units && units.length > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search the ion-header of the page.
|
||||||
|
* This function is usually used to find the header of a page to add buttons.
|
||||||
|
*
|
||||||
|
* @returns The header element if found.
|
||||||
|
*/
|
||||||
|
static async findIonHeaderFromElement(element: HTMLElement): Promise<HTMLElement | null> {
|
||||||
|
await CoreDom.waitToBeInDOM(element);
|
||||||
|
let parentPage: HTMLElement | null = element;
|
||||||
|
|
||||||
|
while (parentPage && parentPage.parentElement) {
|
||||||
|
const content = parentPage.closest<HTMLIonContentElement>('ion-content');
|
||||||
|
if (content) {
|
||||||
|
// Sometimes ion-page class is not yet added by the ViewController, wait for content to render.
|
||||||
|
await content.componentOnReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
parentPage = parentPage.parentElement.closest('.ion-page, .ion-page-hidden, .ion-page-invisible');
|
||||||
|
|
||||||
|
// Check if the page has a header. If it doesn't, search the next parent page.
|
||||||
|
let header = parentPage?.querySelector<HTMLIonHeaderElement>(':scope > ion-header');
|
||||||
|
|
||||||
|
if (header && getComputedStyle(header).display !== 'none') {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find using content if any.
|
||||||
|
header = content?.parentElement?.querySelector<HTMLIonHeaderElement>(':scope > ion-header');
|
||||||
|
|
||||||
|
if (header && getComputedStyle(header).display !== 'none') {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header not found, reject.
|
||||||
|
throw Error('Header not found.');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,7 +37,8 @@ body.core-reading-mode-enabled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-content.core-reading-mode-content {
|
ion-content.core-reading-mode-content,
|
||||||
|
ion-content.core-reading-mode-content core-split-view ion-content {
|
||||||
--background: var(--reading-mode-background, --ion-background-color);
|
--background: var(--reading-mode-background, --ion-background-color);
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue