mirror of
https://github.com/kiwix/kiwix-js-pwa.git
synced 2025-09-11 13:18:21 -04:00
parent
faa729cd62
commit
ba01555e5d
@ -5,6 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: blob: file: about: chrome-extension: ms-appx-web: 'unsafe-inline' 'unsafe-eval';">
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: blob: file: about: chrome-extension: ms-appx-web: 'unsafe-inline' 'unsafe-eval';">
|
||||||
<meta name="description" content="Placeholder for injecting an article into the iframe or window">
|
<meta name="description" content="Placeholder for injecting an article into the iframe or window">
|
||||||
|
<link rel="icon" href="data:,">
|
||||||
</head>
|
</head>
|
||||||
<body></body>
|
<body></body>
|
||||||
</html>
|
</html>
|
@ -4953,6 +4953,7 @@ function readArticle (dirEntry) {
|
|||||||
appstate.expectedArticleURLToBeDisplayed = dirEntry.namespace + '/' + dirEntry.url;
|
appstate.expectedArticleURLToBeDisplayed = dirEntry.namespace + '/' + dirEntry.url;
|
||||||
params.pagesLoaded++;
|
params.pagesLoaded++;
|
||||||
// We must remove focus from UI elements in order to deselect whichever one was clicked (in both Restricted and SW modes),
|
// We must remove focus from UI elements in order to deselect whichever one was clicked (in both Restricted and SW modes),
|
||||||
|
articleContainer = articleContainer || articleWindow;
|
||||||
if (!params.isLandingPage && articleContainer.contentWindow) articleContainer.contentWindow.focus();
|
if (!params.isLandingPage && articleContainer.contentWindow) articleContainer.contentWindow.focus();
|
||||||
uiUtil.pollSpinner()
|
uiUtil.pollSpinner()
|
||||||
// Show the spinner with a loading message
|
// Show the spinner with a loading message
|
||||||
@ -5228,7 +5229,7 @@ function articleLoader (entry, mimeType) {
|
|||||||
|
|
||||||
// Add event listener to iframe window to check for links to external resources
|
// Add event listener to iframe window to check for links to external resources
|
||||||
function filterClickEvent (event) {
|
function filterClickEvent (event) {
|
||||||
// console.debug('filterClickEvent fired');
|
console.debug('filterClickEvent fired');
|
||||||
// Ignore click if we are dealing with an image that has not yet been extracted
|
// Ignore click if we are dealing with an image that has not yet been extracted
|
||||||
if (event.target.dataset && event.target.dataset.kiwixhidden) return;
|
if (event.target.dataset && event.target.dataset.kiwixhidden) return;
|
||||||
// Find the closest enclosing A tag (if any)
|
// Find the closest enclosing A tag (if any)
|
||||||
@ -5244,6 +5245,10 @@ function filterClickEvent (event) {
|
|||||||
// Trap clicks in the iframe to restore Fullscreen mode
|
// Trap clicks in the iframe to restore Fullscreen mode
|
||||||
if (params.lockDisplayOrientation) refreshFullScreen(event);
|
if (params.lockDisplayOrientation) refreshFullScreen(event);
|
||||||
if (clickedAnchor) {
|
if (clickedAnchor) {
|
||||||
|
// Get the window of the clicked anchor
|
||||||
|
articleWindow = clickedAnchor.ownerDocument.defaultView;
|
||||||
|
// Determine if the window is in an iframe
|
||||||
|
articleContainer = (articleWindow.self !== articleWindow.top) ? window.frames[0] : articleWindow;
|
||||||
// This prevents any popover from being displayed when the user clicks on a link
|
// This prevents any popover from being displayed when the user clicks on a link
|
||||||
clickedAnchor.articleisloading = true;
|
clickedAnchor.articleisloading = true;
|
||||||
// Check for Zimit links that would normally be handled by the Replay Worker
|
// Check for Zimit links that would normally be handled by the Replay Worker
|
||||||
@ -5279,24 +5284,58 @@ function filterClickEvent (event) {
|
|||||||
var decHref = decodeURIComponent(href);
|
var decHref = decodeURIComponent(href);
|
||||||
if (!/^(?:#|javascript)/i.test(decHref)) {
|
if (!/^(?:#|javascript)/i.test(decHref)) {
|
||||||
uiUtil.pollSpinner('Loading ' + decHref.replace(/([^/]+)$/, '$1').substring(0, 18) + '...');
|
uiUtil.pollSpinner('Loading ' + decHref.replace(/([^/]+)$/, '$1').substring(0, 18) + '...');
|
||||||
// uiUtil.showSlidingUIElements();
|
// Tear down contents of previous document -- this is needed when a link in a ZIM link in an external window hasn't had
|
||||||
|
// an event listener attached. For example, licks in popovers in external windows.
|
||||||
|
if (articleWindow && articleWindow.document && articleWindow.document.body) {
|
||||||
|
articleWindow.document.body.innerHTML = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var loaded = false;
|
var loaded = false;
|
||||||
|
var unhideArticleTries = 12; // Set up a repeasting loop 12 times (= 6 seconds max) to attempt to unhide the article container
|
||||||
|
|
||||||
|
// Function to unhide a hidden article
|
||||||
|
var unhideArticleContainer = function () {
|
||||||
|
console.debug('Unhiding article container...');
|
||||||
|
if (articleWindow.document) {
|
||||||
|
articleWindow.document.bgcolor = '';
|
||||||
|
if (appstate.target === 'iframe') iframe.style.display = '';
|
||||||
|
if (articleWindow.document.body && articleWindow.document.body.style) {
|
||||||
|
articleWindow.document.body.style.display = 'block';
|
||||||
|
// Some contents need this to be able to display correctly (e.g. masonry landing pages)
|
||||||
|
iframe.style.height = 'auto';
|
||||||
|
resizeIFrame();
|
||||||
|
// Scroll down and up to kickstart lazy loading which might not happen if brower has been slow to display the content
|
||||||
|
articleWindow.scrollBy(0, 5);
|
||||||
|
setTimeout(function () {
|
||||||
|
articleWindow.scrollBy(0, -5);
|
||||||
|
unhideArticleTries = 12; // Reset counter
|
||||||
|
}, 250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main article loader for Service Worker mode
|
||||||
var articleLoadedSW = function (dirEntry, container) {
|
var articleLoadedSW = function (dirEntry, container) {
|
||||||
if (loaded) return;
|
console.debug('Checking if article loaded... ' + loaded);
|
||||||
|
if (loaded) {
|
||||||
|
// Last-ditch attempt to unhide
|
||||||
|
unhideArticleContainer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
loaded = true;
|
loaded = true;
|
||||||
// Get the container windows
|
// Get the container windows
|
||||||
var articleWindow = container.contentWindow || container;
|
articleWindow = container.contentWindow || container;
|
||||||
uiUtil.showSlidingUIElements();
|
uiUtil.showSlidingUIElements();
|
||||||
var doc = articleWindow ? articleWindow.document : null;
|
var doc = articleWindow ? articleWindow.document : null;
|
||||||
articleDocument = doc;
|
articleDocument = doc;
|
||||||
var mimeType = dirEntry.getMimetype();
|
var mimeType = dirEntry.getMimetype();
|
||||||
// If we've successfully loaded an HTML document...
|
// If we've successfully loaded an HTML document...
|
||||||
if (doc && /\bx?html/i.test(mimeType)) {
|
if (doc && /\bx?html/i.test(mimeType)) {
|
||||||
|
console.debug('HTML appears to be available...');
|
||||||
if (params.rememberLastPage) {
|
if (params.rememberLastPage) {
|
||||||
params.lastPageVisit = dirEntry.namespace + '/' + dirEntry.url + '@kiwixKey@' + appstate.selectedArchive.file.name;
|
params.lastPageVisit = dirEntry.namespace + '/' + dirEntry.url + '@kiwixKey@' + appstate.selectedArchive.file.name;
|
||||||
} else {
|
} else {
|
||||||
@ -5310,7 +5349,8 @@ var articleLoadedSW = function (dirEntry, container) {
|
|||||||
settingsStore.setItem(appstate.selectedArchive.file.name, lastPage, Infinity);
|
settingsStore.setItem(appstate.selectedArchive.file.name, lastPage, Infinity);
|
||||||
}
|
}
|
||||||
var docBody = doc ? doc.body : null;
|
var docBody = doc ? doc.body : null;
|
||||||
if (docBody) {
|
if (docBody && docBody.innerHTML) { // docBody must contain contents, otherwise we haven't loaded an article yet
|
||||||
|
console.debug('We appear to have a document body with HTML...');
|
||||||
// Trap clicks in the iframe to enable us to work around the sandbox when opening external links and PDFs
|
// Trap clicks in the iframe to enable us to work around the sandbox when opening external links and PDFs
|
||||||
articleWindow.onclick = filterClickEvent;
|
articleWindow.onclick = filterClickEvent;
|
||||||
// Ensure the window target is permanently stored as a property of the articleWindow (since appstate.target can change)
|
// Ensure the window target is permanently stored as a property of the articleWindow (since appstate.target can change)
|
||||||
@ -5363,14 +5403,17 @@ var articleLoadedSW = function (dirEntry, container) {
|
|||||||
if (/UWP/.test(params.appType)) docBody.addEventListener('pointerup', onPointerUp);
|
if (/UWP/.test(params.appType)) docBody.addEventListener('pointerup', onPointerUp);
|
||||||
// The content is ready : we can hide the spinner
|
// The content is ready : we can hide the spinner
|
||||||
setTab();
|
setTab();
|
||||||
setTimeout(function () {
|
// If the body is not yet displayed, we need to wait for it to be displayed before we can unhide the article container
|
||||||
doc.bgcolor = '';
|
const intervalId = setInterval(function () {
|
||||||
if (appstate.target === 'iframe') container.style.display = '';
|
docBody = articleWindow.document.body;
|
||||||
docBody.style.display = 'block';
|
unhideArticleTries--;
|
||||||
// Some contents need this to be able to display correctly (e.g. masonry landing pages)
|
unhideArticleContainer();
|
||||||
iframe.style.height = 'auto';
|
// Check that the contents of docBody aren't empty and that the unhiding worked
|
||||||
resizeIFrame();
|
if (unhideArticleTries < 1 || docBody.innerHTML && docBody.style.display === 'block') {
|
||||||
}, 200);
|
console.debug('Attempt ' + (12 - unhideArticleTries) + ' to unhide article container...');
|
||||||
|
clearInterval(intervalId);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
uiUtil.clearSpinner();
|
uiUtil.clearSpinner();
|
||||||
// If we reloaded the page to print the desktop style, we need to return to the printIntercept dialogue
|
// If we reloaded the page to print the desktop style, we need to return to the printIntercept dialogue
|
||||||
@ -5391,11 +5434,13 @@ var articleLoadedSW = function (dirEntry, container) {
|
|||||||
popovers.attachKiwixPopoverCss(doc, darkTheme);
|
popovers.attachKiwixPopoverCss(doc, darkTheme);
|
||||||
}
|
}
|
||||||
params.isLandingPage = false;
|
params.isLandingPage = false;
|
||||||
} else {
|
} else if (unhideArticleTries > 0) {
|
||||||
// If we havent' loaded a text-type document, we probably haven't finished loading
|
// If we havent' loaded a text-type document, we probably haven't finished loading
|
||||||
if (!/^text\//i.test(mimeType)) {
|
loaded = false;
|
||||||
loaded = false;
|
unhideArticleTries--;
|
||||||
}
|
// Try again...
|
||||||
|
console.debug('Attempt ' + (12 - unhideArticleTries) + ' to process loaded article...');
|
||||||
|
setTimeout(articleLoadedSW, 250, dirEntry, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show spinner when the article unloads
|
// Show spinner when the article unloads
|
||||||
@ -6102,6 +6147,9 @@ function displayArticleContentInContainer (dirEntry, htmlArticle) {
|
|||||||
htmlArticle = htmlArticle.replace(/<script\b[^>]+-\/(j\/js_modules\/)?script\.js"[^<]*<\/script>/i, '');
|
htmlArticle = htmlArticle.replace(/<script\b[^>]+-\/(j\/js_modules\/)?script\.js"[^<]*<\/script>/i, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a fake favicon to prevent the browser making a useless search for one
|
||||||
|
if (!/<link\s[^>]*rel=["']icon["']/.test(htmlArticle)) htmlArticle = htmlArticle.replace(/(<head\b[^>]*>)(\s*)/i, '$1<link rel="icon" href="data:,">$2');
|
||||||
|
|
||||||
// Gutenberg ZIMs try to initialize before all assets are fully loaded. Affect UWP app.
|
// Gutenberg ZIMs try to initialize before all assets are fully loaded. Affect UWP app.
|
||||||
htmlArticle = htmlArticle.replace(/(<body\s[^<]*onload=(['"]))([^'"]*init\([^'"]+showBooks\([^'"]+)\2/i, '$1setTimeout(function () {$3}, 300);$2');
|
htmlArticle = htmlArticle.replace(/(<body\s[^<]*onload=(['"]))([^'"]*init\([^'"]+showBooks\([^'"]+)\2/i, '$1setTimeout(function () {$3}, 300);$2');
|
||||||
|
|
||||||
@ -6599,8 +6647,7 @@ function displayArticleContentInContainer (dirEntry, htmlArticle) {
|
|||||||
setTab();
|
setTab();
|
||||||
checkToolbar();
|
checkToolbar();
|
||||||
// Show the article
|
// Show the article
|
||||||
articleDocument.bgcolor = '';
|
unhideArticleContainer();
|
||||||
docBody.style.display = 'block';
|
|
||||||
// Jump to any anchor parameter
|
// Jump to any anchor parameter
|
||||||
if (anchorParameter) {
|
if (anchorParameter) {
|
||||||
var target = articleWindow.document.getElementById(anchorParameter);
|
var target = articleWindow.document.getElementById(anchorParameter);
|
||||||
@ -6619,7 +6666,7 @@ function displayArticleContentInContainer (dirEntry, htmlArticle) {
|
|||||||
// Hide the document to avoid display flash before stylesheets are loaded; also improves performance during loading of
|
// Hide the document to avoid display flash before stylesheets are loaded; also improves performance during loading of
|
||||||
// assets in most browsers
|
// assets in most browsers
|
||||||
// DEV: We cannot do `articleWindow.document.documentElement.hidden = true;` because documentElement gets overwritten
|
// DEV: We cannot do `articleWindow.document.documentElement.hidden = true;` because documentElement gets overwritten
|
||||||
// during the document.write() process; and since the latter is synchronous, we get slow display rewrites before it is
|
// during the document.write() process (if used); and since the latter is synchronous, we get slow display rewrites before it is
|
||||||
// effective if we do it after document.close().
|
// effective if we do it after document.close().
|
||||||
// Note that UWP apps cannot communicate to a newly opened window except via postmessage, but Service Worker can still
|
// Note that UWP apps cannot communicate to a newly opened window except via postmessage, but Service Worker can still
|
||||||
// control the Window. Additionally, Edge Legacy cannot build the DOM for a completely hidden document, hence we catch
|
// control the Window. Additionally, Edge Legacy cannot build the DOM for a completely hidden document, hence we catch
|
||||||
@ -6940,6 +6987,10 @@ function addListenersToLink (a, href, baseUrl) {
|
|||||||
// @TODO: We are getting double activations of the click event. This needs debugging. For now, we use a flag to prevent this.
|
// @TODO: We are getting double activations of the click event. This needs debugging. For now, we use a flag to prevent this.
|
||||||
a.newcontainer = true; // Prevents double activation
|
a.newcontainer = true; // Prevents double activation
|
||||||
// uiUtil.showSlidingUIElements();
|
// uiUtil.showSlidingUIElements();
|
||||||
|
// Tear down contents of articleWindow.document
|
||||||
|
if (articleWindow && articleWindow.document && articleWindow.document.body) {
|
||||||
|
articleWindow.document.body.innerHTML = '';
|
||||||
|
}
|
||||||
goToArticle(zimUrl, downloadAttrValue, contentType, zimUrlFullEncoding);
|
goToArticle(zimUrl, downloadAttrValue, contentType, zimUrlFullEncoding);
|
||||||
setTimeout(reset, 1400);
|
setTimeout(reset, 1400);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user