MOBILE-3708 iframe: Display warning in offline

main
Dani Palou 2021-02-26 08:41:00 +01:00
parent 099713b9d2
commit 2c625850bc
3 changed files with 83 additions and 19 deletions

View File

@ -25,10 +25,11 @@ import { CoreTextUtils } from '@services/utils/text';
import { CoreUrlUtils } from '@services/utils/url';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, Network, Platform, NgZone } from '@singletons';
import { makeSingleton, Network, Platform, NgZone, Translate } from '@singletons';
import { CoreLogger } from '@singletons/logger';
import { CoreUrl } from '@singletons/url';
import { CoreWindow } from '@singletons/window';
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
/**
* Possible types of frame elements.
@ -74,21 +75,7 @@ export class CoreIframeUtilsProvider {
}
// The frame has an online URL but the app is offline. Show a warning, or a link if the URL can be opened in the app.
const div = document.createElement('div');
div.setAttribute('text-center', '');
div.setAttribute('padding', '');
div.classList.add('core-iframe-offline-warning');
// @todo Handle link
// Add a class to specify that the iframe is hidden.
element.classList.add('core-iframe-offline-disabled');
if (isSubframe) {
// We cannot apply CSS styles in subframes, just hide the iframe.
element.style.display = 'none';
}
this.addOfflineWarning(element, src, isSubframe);
// If the network changes, check it again.
const subscription = Network.onConnect().subscribe(() => {
@ -124,6 +111,77 @@ export class CoreIframeUtilsProvider {
return false;
}
/**
* Add an offline warning message.
*
* @param element The frame to check (iframe, embed, ...).
* @param src Frame src.
* @param isSubframe Whether it's a frame inside another frame.
* @return Promise resolved when done.
*/
protected async addOfflineWarning(element: HTMLElement, src: string, isSubframe?: boolean): Promise<void> {
const site = CoreSites.getCurrentSite();
const username = site ? site.getInfo()?.username : undefined;
const div = document.createElement('div');
div.classList.add('core-iframe-offline-warning', 'ion-padding', 'ion-text-center');
// Add a class to specify that the iframe is hidden.
element.classList.add('core-iframe-offline-disabled');
if (isSubframe) {
// We cannot apply CSS styles in subframes, just hide the iframe.
element.style.display = 'none';
}
const canHandleLink = await CoreContentLinksHelper.canHandleLink(src, undefined, username);
if (!canHandleLink) {
// @todo: The not connected icon isn't seen due to the div's height. Also, it's quite big.
div.innerHTML = (isSubframe ? '' : '<div class="core-iframe-network-error"></div>') +
'<p>' + Translate.instant('core.networkerroriframemsg') + '</p>';
element.parentElement?.insertBefore(div, element);
return;
}
let link: HTMLElement | undefined;
if (isSubframe) {
// Ionic styles are not available in subframes, adding some minimal inline styles.
link = document.createElement('a');
link.style.display = 'block';
link.style.padding = '1em';
link.style.fontWeight = '500';
link.style.textAlign = 'center';
link.style.textTransform = 'uppercase';
link.style.cursor = 'pointer';
} else {
link = document.createElement('ion-button');
link.setAttribute('expand', 'block');
link.setAttribute('size', 'default');
link.classList.add(
'button',
'button-block',
'button-default',
'button-solid',
'ion-activatable',
'ion-focusable',
);
}
link.innerHTML = Translate.instant('core.viewembeddedcontent');
link.onclick = (event: Event): void => {
CoreContentLinksHelper.handleLink(src, username);
event.preventDefault();
};
div.appendChild(link);
element.parentElement?.insertBefore(div, element);
}
/**
* Given an element, return the content window and document.
* Please notice that the element should be an iframe, embed or similar.

View File

@ -252,4 +252,4 @@ export const NavController = makeSingleton(NavControllerService);
export const Router = makeSingleton(RouterService, ['routerState', 'url']);
// Convert external libraries injectables.
export const Translate = makeSingleton(TranslateService, ['onLangChange']);
export const Translate = makeSingleton(TranslateService, ['onLangChange', 'translations']);

View File

@ -95,7 +95,8 @@ ion-button.button-small ion-icon.faicon[slot] {
}
// Ionic alert.
ion-alert.core-alert-network-error .alert-head {
ion-alert.core-alert-network-error .alert-head,
div.core-iframe-network-error {
position: relative;
content: " ";
background: url("/assets/fonts/font-awesome/solid/wifi.svg") no-repeat 50% 50%;
@ -113,7 +114,8 @@ ion-alert.core-alert-network-error .alert-head {
mask: url("/assets/fonts/font-awesome/solid/exclamation-triangle.svg") no-repeat 50% 50%;
}
}
[dir=rtl] ion-alert.core-alert-network-error .alert-head::after {
[dir=rtl] ion-alert.core-alert-network-error .alert-head::after,
[dir=rtl] div.core-iframe-network-error::after {
right: unset;
left: -15%;
}
@ -442,3 +444,7 @@ ion-button.core-button-select {
.core-monospaced {
font-family: Andale Mono,Monaco,Courier New,DejaVu Sans Mono,monospace;
}
.core-iframe-offline-disabled {
display: none !important;
}