blob: aab477f916c18a57338f1d74e8860179ff95b5ba [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
var isWp81 = navigator.appVersion.indexOf('Windows Phone 8.1') !== -1;
var isWp10 = navigator.appVersion.indexOf('Windows Phone 10') !== -1;
var isPhoneDevice = isWp81 || isWp10;
var isWin10UWP = navigator.appVersion.indexOf('MSAppHost/3.0') !== -1;
var isHosted = window.location.protocol.indexOf('http') === 0;
var isMsAppxWeb = window.location.protocol.indexOf('ms-appx-web') === 0;
var schema = isHosted || (isWin10UWP && isMsAppxWeb) ? 'ms-appx-web' : 'ms-appx';
var fileName = isWp81 ? 'splashscreenphone.png' : 'splashscreen.png';
var splashImageSrc = schema + ':///images/' + fileName;
var splashElement = null;
var extendedSplashImage = null;
var extendedSplashProgress = null;
var extendedSplashImageHelper = null;
/// / <Config and initialization>
var DEFAULT_SPLASHSCREEN_DURATION = 3000; // in milliseconds
var DEFAULT_FADE_DURATION = 500; // in milliseconds
var FPS = 60; // frames per second used by requestAnimationFrame
var PROGRESSRING_HEIGHT = 40;
var PROGRESSRING_BOTTOM_MARGIN = 10; // needed for windows 10 min height window
var bgColor = '#464646';
var isBgColorTransparent = false;
var titleInitialBgColor;
var titleBgColor;
var autoHideSplashScreen = true;
var splashScreenDelay = DEFAULT_SPLASHSCREEN_DURATION;
var fadeSplashScreen = true;
var fadeSplashScreenDuration = DEFAULT_FADE_DURATION;
var showSplashScreenSpinner = true;
var splashScreenSpinnerColor; // defaults to system accent color
var effectiveSplashDuration;
function readBoolFromCfg (preferenceName, defaultValue, cfg) {
var value = cfg.getPreferenceValue(preferenceName);
if (typeof value !== 'undefined') {
return value === 'true';
} else {
return defaultValue;
}
}
function readPreferencesFromCfg (cfg, manifest) {
try {
// Update splashscreen image path to match application manifest
splashImageSrc = schema + ':///' + manifest.getSplashScreenImagePath().replace(/\\/g, '/');
bgColor = cfg.getPreferenceValue('SplashScreenBackgroundColor') || bgColor;
bgColor = bgColor.toLowerCase().replace('0x', '#');
isBgColorTransparent = (bgColor === 'transparent');
if (!isBgColorTransparent) {
if (bgColor.length > 7) {
// Remove alpha
bgColor = bgColor.slice(0, 1) + bgColor.slice(3, bgColor.length);
}
titleBgColor = {
a: 255,
r: parseInt(bgColor.slice(1, 3), 16),
g: parseInt(bgColor.slice(3, 5), 16),
b: parseInt(bgColor.slice(5, 7), 16)
};
}
autoHideSplashScreen = readBoolFromCfg('AutoHideSplashScreen', autoHideSplashScreen, cfg);
splashScreenDelay = cfg.getPreferenceValue('SplashScreenDelay') || splashScreenDelay;
fadeSplashScreen = readBoolFromCfg('FadeSplashScreen', fadeSplashScreen, cfg);
fadeSplashScreenDuration = cfg.getPreferenceValue('FadeSplashScreenDuration') || fadeSplashScreenDuration;
showSplashScreenSpinner = readBoolFromCfg('ShowSplashScreenSpinner', showSplashScreenSpinner, cfg);
splashScreenSpinnerColor = cfg.getPreferenceValue('SplashScreenSpinnerColor');
effectiveSplashDuration = Math.max(splashScreenDelay - fadeSplashScreenDuration, 0);
} catch (e) {
var msg = '[Windows][SplashScreen] Error occured on loading preferences from config.xml: ' + JSON.stringify(e);
console.error(msg);
}
}
function isPortrait () {
return window.innerHeight > window.innerWidth;
}
function init (config, manifest) {
readPreferencesFromCfg(config, manifest);
var splashscreenStyles = document.createElement('link');
splashscreenStyles.rel = 'stylesheet';
splashscreenStyles.type = 'text/css';
splashscreenStyles.href = '/www/css/splashscreen.css';
document.head.appendChild(splashscreenStyles);
// Windows 8.1 Desktop
// <div id='extendedSplashScreen' class='extendedSplashScreen hidden'>
// <img id='extendedSplashImage' src='/images/SplashScreen.png' alt='Splash screen image' />
// <progress id='extendedSplashProgress' class='win-medium win-ring'></progress>
// </div>
splashElement = document.createElement('div');
splashElement.id = 'extendedSplashScreen';
splashElement.classList.add('extendedSplashScreen');
splashElement.classList.add('hidden');
splashElement.style.backgroundColor = bgColor;
extendedSplashImageHelper = document.createElement('span');
extendedSplashImageHelper.id = 'extendedSplashImageHelper';
extendedSplashImage = document.createElement('img');
extendedSplashImage.id = 'extendedSplashImage';
extendedSplashImage.alt = 'Splash screen image';
// Disabling image drag
var draggableAttr = document.createAttribute('draggable');
draggableAttr.value = 'false';
extendedSplashImage.attributes.setNamedItem(draggableAttr);
// This helps prevent flickering by making the system wait until your image has been rendered
// before it switches to your extended splash screen.
var onloadAttr = document.createAttribute('onload');
onloadAttr.value = '';
extendedSplashImage.attributes.setNamedItem(onloadAttr);
extendedSplashImage.src = splashImageSrc;
extendedSplashProgress = document.createElement('progress');
extendedSplashProgress.id = 'extendedSplashProgress';
extendedSplashProgress.classList.add('win-medium');
extendedSplashProgress.classList.add('win-ring');
extendedSplashImage.src = splashImageSrc;
if (isPhoneDevice) {
extendedSplashImage.classList.add('phone');
}
if (isWp81) {
extendedSplashProgress.classList.add('extended-splash-progress-phone');
} else if (isWp10) {
extendedSplashProgress.classList.add('extended-splash-progress-wp10');
} else {
extendedSplashProgress.classList.add('extended-splash-progress-desktop');
}
if (!showSplashScreenSpinner) {
extendedSplashProgress.classList.add('hidden');
}
if (typeof splashScreenSpinnerColor !== 'undefined') {
extendedSplashProgress.style.color = splashScreenSpinnerColor;
}
splashElement.appendChild(extendedSplashImageHelper);
splashElement.appendChild(extendedSplashImage);
splashElement.appendChild(extendedSplashProgress);
document.body.appendChild(splashElement);
}
/// / </Config and initialization>
/// / <UI>
var origOverflow, origZooming;
function disableUserInteraction () {
origOverflow = document.documentElement.style.overflow;
document.documentElement.style.overflow = 'hidden';
origZooming = document.body.style['-ms-content-zooming'];
document.body.style['-ms-content-zooming'] = 'none';
}
function enableUserInteraction () {
document.documentElement.style.overflow = origOverflow;
document.body.style['-ms-content-zooming'] = origZooming;
}
// Enter fullscreen mode
function enterFullScreen () {
if (Windows.UI.ViewManagement.ApplicationViewBoundsMode) { // else crash on 8.1
var view = Windows.UI.ViewManagement.ApplicationView.getForCurrentView();
view.setDesiredBoundsMode(Windows.UI.ViewManagement.ApplicationViewBoundsMode.useCoreWindow);
view.suppressSystemOverlays = true;
}
}
// Exit fullscreen mode
function exitFullScreen () {
if (Windows.UI.ViewManagement.ApplicationViewBoundsMode) { // else crash on 8.1
var view = Windows.UI.ViewManagement.ApplicationView.getForCurrentView();
view.setDesiredBoundsMode(Windows.UI.ViewManagement.ApplicationViewBoundsMode.useVisible);
view.suppressSystemOverlays = false;
}
}
// Make title bg color match splashscreen bg color
function colorizeTitleBar () {
var appView = Windows.UI.ViewManagement.ApplicationView.getForCurrentView();
if (isWin10UWP && !isBgColorTransparent) {
titleInitialBgColor = appView.titleBar.backgroundColor;
appView.titleBar.backgroundColor = titleBgColor;
appView.titleBar.buttonBackgroundColor = titleBgColor;
}
}
// Revert title bg color
function revertTitleBarColor () {
var appView = Windows.UI.ViewManagement.ApplicationView.getForCurrentView();
if (isWin10UWP && !isBgColorTransparent) {
appView.titleBar.backgroundColor = titleInitialBgColor;
appView.titleBar.buttonBackgroundColor = titleInitialBgColor;
}
}
// Displays the extended splash screen. Pass the splash screen object retrieved during activation.
function show () {
enterFullScreen();
colorizeTitleBar();
disableUserInteraction();
positionControls();
// Once the extended splash screen is setup, apply the CSS style that will make the extended splash screen visible.
WinJS.Utilities.removeClass(splashElement, 'hidden');
}
function positionControls () {
if (isWp10) {
// Resize happens twice sometimes, ensure the image is properly positioned
if (splash.imageLocation.y !== 0) {
if (isPortrait()) {
extendedSplashProgress.style.top = window.innerHeight * (2 / 3 + 1 / 6) - PROGRESSRING_HEIGHT / 2 + 'px';
} else {
extendedSplashProgress.style.top = Math.min(window.innerHeight - PROGRESSRING_HEIGHT - PROGRESSRING_BOTTOM_MARGIN, splash.imageLocation.y + splash.imageLocation.height + 32) + 'px';
}
}
return;
}
// Position the extended splash screen image in the same location as the system splash screen image.
if (isPhoneDevice) {
extendedSplashImage.style.top = 0;
extendedSplashImage.style.left = 0;
} else {
// Avoiding subtle image shift on desktop
extendedSplashImage.style.left = splash.imageLocation.x + 'px';
extendedSplashImage.style.top = splash.imageLocation.y + 'px';
}
if (!isWp81) {
extendedSplashImage.style.height = splash.imageLocation.height + 'px';
extendedSplashImage.style.width = splash.imageLocation.width + 'px';
extendedSplashProgress.style.marginTop = Math.min(window.innerHeight - PROGRESSRING_HEIGHT - PROGRESSRING_BOTTOM_MARGIN, splash.imageLocation.y + splash.imageLocation.height + 32) + 'px';
}
}
// Updates the location of the extended splash screen image. Should be used to respond to window size changes.
function updateImageLocation () {
if (isVisible()) {
positionControls();
}
}
// Checks whether the extended splash screen is visible and returns a boolean.
function isVisible () {
return !(WinJS.Utilities.hasClass(splashElement, 'hidden'));
}
function fadeOut (el, duration, finishCb) {
var opacityDelta = 1 / (FPS * duration / 1000);
el.style.opacity = 1;
(function fade () {
if ((el.style.opacity -= opacityDelta) < 0) {
finishCb();
} else {
requestAnimationFrame(fade);
}
})();
}
// Removes the extended splash screen if it is currently visible.
function hide () {
if (isVisible()) {
var hideFinishCb = function () {
WinJS.Utilities.addClass(splashElement, 'hidden');
splashElement.style.opacity = 1;
enableUserInteraction();
exitFullScreen();
};
// Color reversion before fading is over looks better:
revertTitleBarColor();
// https://issues.apache.org/jira/browse/CB-11751
// This can occur when we directly replace whole document.body f.e. in a router.
// Note that you should disable the splashscreen in this case or update a container element instead.
if (document.getElementById(splashElement.id) == null) {
hideFinishCb();
return;
}
if (fadeSplashScreen) {
fadeOut(splashElement, fadeSplashScreenDuration, hideFinishCb);
} else {
hideFinishCb();
}
}
}
/// / </UI>
/// / <Events>
var splash = null; // Variable to hold the splash screen object.
function activated (eventObject) {
// Retrieve splash screen object
splash = eventObject.detail.splashScreen;
// Register an event handler to be executed when the splash screen has been dismissed.
splash.addEventListener('dismissed', onSplashScreenDismissed, false);
// Listen for window resize events to reposition the extended splash screen image accordingly.
// This is important to ensure that the extended splash screen is formatted properly in response to snapping, unsnapping, rotation, etc...
window.addEventListener('resize', onResize, false);
}
function onSplashScreenDismissed () {
// Include code to be executed when the system has transitioned from the splash screen to the extended splash screen (application's first view).
if (autoHideSplashScreen) {
window.setTimeout(hide, effectiveSplashDuration);
}
}
function onResize () {
// Safely update the extended splash screen image coordinates. This function will be fired in response to snapping, unsnapping, rotation, etc...
if (splash) {
// Update the coordinates of the splash screen image.
updateImageLocation(splash);
}
}
/// / </Events>
module.exports = {
firstShow: function (config, manifest, activatedEventArgs) {
init(config, manifest);
activated(activatedEventArgs);
if (!isVisible() && (splashScreenDelay > 0 || !autoHideSplashScreen)) {
show();
}
},
show: function () {
if (!isVisible()) {
show();
}
},
hide: function () {
if (isVisible()) {
hide();
}
}
};