Skip to content

Commit

Permalink
Add Wikipedia preview function #278 (#595)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaifroid authored May 12, 2024
1 parent 1f613e6 commit 7a072ad
Show file tree
Hide file tree
Showing 11 changed files with 500 additions and 46 deletions.
2 changes: 2 additions & 0 deletions KiwixWebApp-github.jsproj
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,9 @@
<Content Include="www\img\icons\map_marker-30px.png" />
<Content Include="www\img\icons\map_marker-18px.png" />
<Content Include="www\img\icons\new_window.svg" />
<Content Include="www\img\icons\new_window_black.svg" />
<Content Include="www\img\icons\new_window_lb.svg" />
<Content Include="www\img\icons\new_window_white.svg" />
<Content Include="www\img\icons\wikimed-blue-32.png" />
<Content Include="www\img\icons\wikimed-lightblue-32.png" />
<Content Include="www\img\icons\wikivoyage-black-32.png" />
Expand Down
2 changes: 2 additions & 0 deletions KiwixWebApp.jsproj
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,9 @@
<Content Include="www\img\icons\map_marker-30px.png" />
<Content Include="www\img\icons\map_marker-18px.png" />
<Content Include="www\img\icons\new_window.svg" />
<Content Include="www\img\icons\new_window_black.svg" />
<Content Include="www\img\icons\new_window_lb.svg" />
<Content Include="www\img\icons\new_window_white.svg" />
<Content Include="www\img\icons\wikimed-blue-32.png" />
<Content Include="www\img\icons\wikimed-lightblue-32.png" />
<Content Include="www\img\icons\wikivoyage-black-32.png" />
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ try switching the app to Restricted mode (see Content injection mode in Configur

+ <img src="images/googlechrome-color.svg" width="20" /> Google Chrome / Chromium >= 59 (and many browsers based on Chromium, e.g. Opera, Samsung Internet)
+ <img src="images/microsoftedge-color.svg" width="20" /> Microsoft Edge (Chromium) >= 79
+ <img src="images/firefoxbrowser-color.svg" width="20" /> Mozilla Firefox >= 60 (but see note about Android`*`)
+ <img src="images/firefoxbrowser-color.svg" width="20" /> Mozilla Firefox >= 68 (but see note about Android`*`)
+ <img src="images/safari-color.svg" width="20" /> Apple Safari >= 11.3 for iOS and macOS (full-text search only works on iOS 15+)
+ <img src="images/edgelegacy-color.svg" width="22" /> Microsoft Edge Legacy 18 (Windows only)

Expand All @@ -101,7 +101,7 @@ Although deprecated, we will keep support for as long as is practical:

* Internet Explorer 11 (Restricted mode only, no offline use of PWA)
* Edge Legacy <= 17 (Restricted mode only, no offline use of PWA)
* Firefox 45-59 (some versions require the user to switch manually to Restricted mode)
* Firefox 45-67 (some versions require the user to switch manually to Restricted mode, and some are unable to display WebP images)
* Chromium 49-58 (some versions only run in Restricted mode)

## Reporting bugs and technical support
Expand Down
4 changes: 4 additions & 0 deletions service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ const precacheFiles = [
'www/img/icons/wikivoyage-white-32.png',
'www/img/icons/map_marker-30px.png',
'www/img/icons/map_marker-18px.png',
'www/img/icons/new_window.svg',
'www/img/icons/new_window_black.svg',
'www/img/icons/new_window_lb.svg',
'www/img/icons/new_window_white.svg',
'www/img/spinner.gif',
'www/index.html',
'www/article.html',
Expand Down
2 changes: 1 addition & 1 deletion www/-/s/style-dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ tr[style*="background: antiquewhite"], tr[style*="background-color:#ee"], tr[sty
.mw-ui-button[style*="background"], .mw-ui-button[style*="background"] *, .wikiEditor-ui,
table.navbox.collapsible tr:nth-child(2) > td, div.menu, div.NavHead, .oo-ui-popupWidget-popup,
.oo-ui-buttonElement-button, .mw-notification, .mwe-popups, .mwe-popups-is-not-tall, .mwe-popups-is-tall,
.ui-widget-content, .oo-ui-window-body, #pagehistory li.selected, .tracklist tr, .dataTable tr {
.ui-widget-content, .oo-ui-window-body, #pagehistory li.selected, .tracklist tr, .dataTable tr, div.kiwixtooltip {
background-color: #222 !important;
}

Expand Down
8 changes: 8 additions & 0 deletions www/img/icons/new_window_black.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions www/img/icons/new_window_white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,7 @@ <h4 class="panel-group-heading" id="privacy">Privacy settings</h4>
<div class="row">
<h4 class="panel-group-heading">Performance / compatibility</h4>
<div class="panel panel-warning" id="performanceSettingsDiv">
<div class="panel-heading">Speed up archive access</div>
<div class="panel-heading">Caching and preview settings</div>
<div class="panel-body">
<div class="row">
<div class="col-sm-6">
Expand Down Expand Up @@ -1169,6 +1169,11 @@ <h4 class="panel-group-heading">Performance / compatibility</h4>
</div>
</div>
</div>
<label class="checkbox" title="Shows a small popup preview of Wikipedia and Wikivoyage articles when the pointer is hovered over an article link. Turn this off if it is too slow or interferes wtih display of articles on small-screen devices.">
<input type="checkbox" name="showPopoverPreviews" id="showPopoverPreviewsCheck">
<span class="checkmark"></span>
<b>Show a popover preview of <i>Wikipedia / Wkivoyage</i> articles when hovering over links</b> (<i>limited functionality in Restricted mode</i>)
</label>
</div>
</div>
<div class="panel panel-warning" style="min-width:16em;" id="mathsProcessingMode">
Expand Down
146 changes: 104 additions & 42 deletions www/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2096,6 +2096,11 @@ function setWindowOpenerUI () {
newWin.style.display = 'none';
}
}
document.getElementById('showPopoverPreviewsCheck').addEventListener('change', function (e) {
params.showPopoverPreviews = e.target.checked;
settingsStore.setItem('showPopoverPreviews', params.showPopoverPreviews, Infinity);
params.themeChanged = true;
});
document.getElementById('allowHTMLExtractionCheck').addEventListener('click', function (e) {
params.allowHTMLExtraction = e.target.checked;
var alertMessage = '';
Expand Down Expand Up @@ -5205,18 +5210,20 @@ function articleLoader (entry, mimeType) {
// Add event listener to iframe window to check for links to external resources
function filterClickEvent (event) {
// console.debug('filterClickEvent fired');
if (params.contentInjectionMode === 'jquery') return;
// Ignore click if we are dealing with an image that has not yet been extracted
if (event.target.dataset && event.target.dataset.kiwixhidden) return;
// Trap clicks in the iframe to restore Fullscreen mode
if (params.lockDisplayOrientation) refreshFullScreen(event);
// Find the closest enclosing A tag (if any)
var clickedAnchor = uiUtil.closestAnchorEnclosingElement(event.target);
// If the anchor has a passthrough property, then we have already checked it is safe, so we can return
if (clickedAnchor && clickedAnchor.passthrough) {
clickedAnchor.passthrough = false;
return;
}
// Remove any Kiwix Popovers that may be hanging around
uiUtil.removeKiwixPopoverDivs(event.target.ownerDocument);
if (params.contentInjectionMode === 'jquery') return;
// Trap clicks in the iframe to restore Fullscreen mode
if (params.lockDisplayOrientation) refreshFullScreen(event);
if (clickedAnchor) {
// Check for Zimit links that would normally be handled by the Replay Worker
// DEV: '__WB_pmw' is a function inserted by wombat.js, so this detects links that have been rewritten in zimit2 archives
Expand Down Expand Up @@ -5354,6 +5361,9 @@ var articleLoadedSW = function (dirEntry, container) {
anchorParameter = '';
}
if (dirEntry) uiUtil.makeReturnLink(dirEntry.getTitleOrUrl());
if (appstate.wikimediaZimLoaded && params.showPopoverPreviews) {
uiUtil.attachKiwixPopoverCss(doc, params.cssTheme === 'darkReader');
}
params.isLandingPage = false;
} else {
// If we havent' loaded a text-type document, we probably haven't finished loading
Expand Down Expand Up @@ -6518,7 +6528,9 @@ function displayArticleContentInContainer (dirEntry, htmlArticle) {
parseAnchorsJQuery(dirEntry);
loadCSSJQuery();
images.prepareImagesJQuery(articleWindow);
// loadJavascript(); //Disabled for now, since it does nothing - also, would have to load before images, ideally through controlled css loads above
if (appstate.wikimediaZimLoaded && params.showPopoverPreviews) {
uiUtil.attachKiwixPopoverCss(articleWindow.document);
}
var determinedTheme = params.cssTheme === 'auto' ? cssUIThemeGetOrSet('auto') : params.cssTheme;
if (params.allowHTMLExtraction && appstate.target === 'iframe') {
uiUtil.insertBreakoutLink(determinedTheme);
Expand Down Expand Up @@ -6547,6 +6559,8 @@ function displayArticleContentInContainer (dirEntry, htmlArticle) {
}
anchorParameter = '';
}
// Trap clicks in the iframe (currently only used for removing popovers in Restricted mode)
articleWindow.onclick = filterClickEvent;
params.isLandingPage = false;
};

Expand Down Expand Up @@ -6711,15 +6725,14 @@ function loadCSSJQuery () {
// These sections can be opened by clicking on them, but this is done with some javascript.
// The code below is a workaround we still need for compatibility with ZIM files generated by mwoffliner in 2018.
// A better fix has been made for more recent ZIM files, with the use of noscript tags : see https://github.com/openzim/mwoffliner/issues/324
var iframe = articleContainer.contentDocument;
var collapsedBlocks = iframe.querySelectorAll('.collapsible-block:not(.open-block), .collapsible-heading:not(.open-block)');
var collapsedBlocks = articleDocument.querySelectorAll('.collapsible-block:not(.open-block), .collapsible-heading:not(.open-block)');
// Using decrementing loop to optimize performance : see https://stackoverflow.com/questions/3520688
for (var i = collapsedBlocks.length; i--;) {
collapsedBlocks[i].classList.add('open-block');
}
var cssCount = 0;
var cssFulfilled = 0;
Array.prototype.slice.call(iframe.querySelectorAll('link[data-kiwixurl]')).forEach(function (link) {
Array.prototype.slice.call(articleDocument.querySelectorAll('link[data-kiwixurl]')).forEach(function (link) {
cssCount++;
var linkUrl = link.getAttribute('data-kiwixurl');
var url = decodeURIComponent(/zimit/.test(appstate.selectedArchive.zimType) ? linkUrl : uiUtil.removeUrlParameters(linkUrl));
Expand Down Expand Up @@ -6804,6 +6817,7 @@ function addListenersToLink (a, href, baseUrl) {
a.newcontainer = false;
}
loadingContainer = false;
a.articleloading = false;
};
var onDetectedClick = function (e) {
// Restore original values for this window/tab
Expand Down Expand Up @@ -6875,49 +6889,79 @@ function addListenersToLink (a, href, baseUrl) {
setTimeout(reset, 1400);
};

var darkTheme = (params.cssUITheme == 'auto' ? cssUIThemeGetOrSet('auto', true) : params.cssUITheme) !== 'light';

/* Event processing */
a.addEventListener('touchstart', function (e) {
if (!params.windowOpener || a.touched) return;
e.stopPropagation();
// e.preventDefault();
// console.debug('a.touchstart');
var timeout = 500;
if (!appstate.wikimediaZimLoaded || !params.showPopoverPreviews) {
if (!params.windowOpener || a.touched) return;
loadingContainer = true;
} else {
timeout = 200;
}
a.touched = true;
loadingContainer = true;
var event = e;
// The link will be clicked if the user long-presses for more than 800ms (if the option is enabled)
// The link will be clicked if the user long-presses for more than 500ms (if the option is enabled), or 200ms for popover
setTimeout(function () {
// DEV: appstate.startVector indicates that the app is processing a touch zoom event, so we cancel any new windows
// see uiUtil.pointermove_handler
if (!a.touched || a.newcontainer || appstate.startVector) return;
e.preventDefault();
a.newcontainer = true;
onDetectedClick(event);
}, 800);
if (appstate.wikimediaZimLoaded && params.showPopoverPreviews) {
a.dataset.touchevoked = true;
uiUtil.attachKiwixPopoverDiv(event, a, baseUrl, darkTheme);
} else {
a.newcontainer = true;
onDetectedClick(event);
}
event.preventDefault();
}, timeout);
}, { passive: false });
a.addEventListener('touchend', function () {
// console.debug('a.touchend');
a.touched = false;
a.newcontainer = false;
loadingContainer = false;
// Cancel any popovers because user has clicked
a.articleloading = true;
setTimeout(reset, 1000);
});
// This detects right-click in all browsers (only if the option is enabled)
a.addEventListener('contextmenu', function (e) {
console.debug('contextmenu');
if (!params.windowOpener) return;
if (params.rightClickType === 'double' && !a.touched) {
a.touched = true;
setTimeout(function () {
a.touched = false;
}, 700);
} else {
if (a.newcontainer) return; // Prevent accidental double activation
// console.debug('contextmenu');
if (appstate.wikimediaZimLoaded && params.showPopoverPreviews) {
e.preventDefault();
e.stopPropagation();
a.newcontainer = true;
a.touched = false;
onDetectedClick(e);
// console.debug('suppressed contextmenu because processing popovers');
var kiwixPopover = e.target.ownerDocument.querySelector('.kiwixtooltip');
if (kiwixPopover) {
// return;
} else if (!a.touched) {
a.touched = true;
uiUtil.attachKiwixPopoverDiv(e, a, baseUrl, darkTheme);
}
} else {
if (!params.windowOpener) return;
if (params.rightClickType === 'double' && !a.touched) {
a.touched = true;
setTimeout(function () {
a.touched = false;
}, 700);
} else {
if (a.newcontainer) return; // Prevent accidental double activation
e.preventDefault();
e.stopPropagation();
a.newcontainer = true;
a.touched = false;
onDetectedClick(e);
}
}
});
// This traps the middle-click event before tha auxclick event fires
a.addEventListener('mousedown', function (e) {
console.debug('mosuedown');
// console.debug('a.mousedown');
a.dataset.touchevoked = true; // This is needed to simulate touch events in UWP app
if (!params.windowOpener) return;
e.preventDefault();
e.stopPropagation();
Expand All @@ -6926,22 +6970,49 @@ function addListenersToLink (a, href, baseUrl) {
a.newcontainer = true;
onDetectedClick(e);
} else {
console.debug('suppressed mousedown');
// console.debug('suppressed mousedown');
}
});
// This detects the middle-click event that opens a new tab in recent Firefox and Chrome
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event
a.addEventListener('auxclick', function (e) {
console.debug('auxclick');
// console.debug('a.auxclick');
if (!params.windowOpener) return;
e.preventDefault();
e.stopPropagation();
});
// The popover feature requires as a minimum that the browser supports the css matches function
// (having this condition prevents very erratic popover placement in IE11, for example, so the feature is disabled)
if (appstate.wikimediaZimLoaded && params.showPopoverPreviews && 'matches' in Element.prototype) {
a.addEventListener('mouseover', function (e) {
// console.debug('a.mouseover');
if (a.dataset.touchevoked) return;
uiUtil.attachKiwixPopoverDiv(e, a, baseUrl, darkTheme);
});
a.addEventListener('mouseout', function (e) {
if (a.dataset.touchevoked) return;
uiUtil.removeKiwixPopoverDivs(e.target.ownerDocument);
});
a.addEventListener('focus', function (e) {
setTimeout(function () { // Delay focus event so touchstart can fire first
// console.debug('a.focus');
if (a.touched) return;
a.focused = true;
uiUtil.attachKiwixPopoverDiv(e, a, baseUrl, darkTheme);
}, 200);
});
a.addEventListener('blur', function (e) {
// console.debug('a.blur');
a.focused = false;
});
}
// The main click routine (called by other events above as well)
a.addEventListener('click', function (e) {
console.log('Click event', e);
console.log('a.click', e);
// Cancel any popovers because user has clicked
a.articleloading = true;
// Prevent opening multiple windows
if (loadingContainer || a.touched || a.newcontainer) {
if (loadingContainer || a.touched) {
e.preventDefault();
e.stopPropagation();
} else {
Expand Down Expand Up @@ -6969,15 +7040,6 @@ function displayHiddenBlockElements (win, doc) {
'app to decide when to apply the setting. If you never want to see hidden elements, even in Wikimedia ZIMs, change the ' +
'setting to <b>never</b>.</p>';
}
// else if (params.displayHiddenBlockElements === 'auto') {
// message = '<p>There is a new <b>auto</b> setting in Configuration to display hidden elements (navigation boxes, series tables) ' +
// "in Wikimedia ZIMs. This is now on by default. If you don't want to see these elements, change the 'Display hidden block elements' " +
// "setting to <b>never</b> (under 'Display style').</p>";
// if (params.cssSource !== 'desktop') {
// message += '<p>Please note that hidden elements are <i>always</i> displayed in Desktop style (regardless of the setting)' +
// (params.cssSource !== 'desktop' ? '. You can switch the display style to Desktop in Configuration' : '') + '.</p>';
// }
// }
if (message) {
message += '<p><i>This message will not be displayed again, unless you reset the app.</i></p>';
params.noHiddenElementsWarning = true;
Expand Down
Loading

0 comments on commit 7a072ad

Please sign in to comment.