Skip to content

Commit

Permalink
Merge pull request #851 from basics/feature/entry-battery-level-check
Browse files Browse the repository at this point in the history
fix(entry): added battery level check
  • Loading branch information
StephanGerbeth authored Apr 21, 2024
2 parents 5ebf03e + df17692 commit 8e48dab
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 5 deletions.
4 changes: 3 additions & 1 deletion docs/src/guide/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ These options can be used to define the initial checks to display the [`BoosterL
````js
{
performance: true,
browserSupport: true
browserSupport: true,
battery: true
}
````

| Key | Type | Required | Description | Default |
| ---------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `performance` | `Boolean` | yes | Checking whether the [minimum characteristic values](/guide/options#performancemetrics) have been reached. If the test is negative, the [`BoosterLayer`](/components/booster-layer) will be displayed. | `true` |
| `browserSupport` | `Boolean` | yes | Check if the current browser on client side is supported. If the test is negative, the [`BoosterLayer`](/components/booster-layer) will be displayed. | `true` |
| `battery` | `Boolean` | yes | Check if the current user save power in browser. If the test is negative, the [`BoosterLayer`](/components/booster-layer) will be displayed. | `true` |

::: info
For the browser support detection, the default [Browserslist](https://github.com/browserslist/browserslist) of the NuxtJS configuration is used.
Expand Down
1 change: 1 addition & 0 deletions playground/components/InfoLayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<li id="nuxt-booster-message-unsupported-browser">outdated browser</li>
<li id="nuxt-booster-message-reduced-bandwidth">reduced-bandwidth</li>
<li id="nuxt-booster-message-weak-hardware">weak hardware</li>
<li id="nuxt-booster-message-low-battery">low battery</li>
</ul>
<div class="info-layer-buttons">
<base-button
Expand Down
Binary file added src/media/video.mp4
Binary file not shown.
14 changes: 13 additions & 1 deletion src/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { optimizePreloads } from './utils/preload';
import { getSupportedBrowserDetector } from './utils/browser';
import { registerAppEntry as registerAppEntryWebpack } from './hookFunctions/webpack';
import { registerAppEntry as registerAppEntryVite } from './hookFunctions/vite';
import { getTemplate as getBlobFileTemplate } from './utils/blob';

import pluginTemplate from './tmpl/plugin.tmpl';
import entryTemplate from './tmpl/entry.tmpl';
Expand Down Expand Up @@ -147,13 +148,24 @@ async function addBuildTemplates(nuxt, options) {
entry: join(nuxt.options.appDir, 'entry'),
runOptions: options.runOptions,
ssr: nuxt.options.ssr,
ignorePerformance: !options.detection.performance,
ignore: {
battery: !options.detection.battery,
performance: !options.detection.performance
},
performanceMetrics: JSON.stringify(options.performanceMetrics || {}),
supportedBrowserDetector
});
},
write: true
});

const files = [['video', resolver.resolve('media/video.mp4')]];
const mediaContent = await getBlobFileTemplate(files);
addTemplate({
getContents: () => mediaContent,
filename: MODULE_NAME + '/blobs.mjs',
write: true
});
}

async function addModules(nuxt, moduleOptions) {
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/components/BoosterLayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<li id="nuxt-booster-message-reduced-bandwidth">slow connection</li>
<!-- Displayed when user hardware are not sufficient. -->
<li id="nuxt-booster-message-weak-hardware">weak hardware</li>
<!-- Displayed when the user batteries are not sufficient. -->
<li id="nuxt-booster-message-low-battery">low battery</li>
</ul>

<!-- Button to hide the layer with no javascript -->
Expand Down Expand Up @@ -96,5 +98,9 @@ useHead({
display: none;
}
#nuxt-speedkit-message-low-battery {
display: none;
}
/*! purgecss end ignore */
</style>
41 changes: 41 additions & 0 deletions src/runtime/utils/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,44 @@ export function initReducedView() {
tmp.remove();
});
}

export async function hasBatteryPerformanceIssue(videoBlob) {
try {
if (await isBatteryLow()) {
throw new Error('Battery is low.');
}
} catch (error) {
if (error.message === 'Battery is low.') {
throw error;
}
await canVideoPlay(videoBlob);
}
}

/**
* Checks if battery still has enough energy.
* This check is for Chrome and all other browsers that support this setting.
*
* Condition is: The device is not charging and Battery is below <= 20%.
* @see https://blog.google/products/chrome/new-chrome-features-to-save-battery-and-make-browsing-smoother/
* @see https://developer.chrome.com/blog/memory-and-energy-saver-mode/
**/
async function isBatteryLow() {
const MIN_BATTERY_LEVEL = 0.2;
const battery = await window.navigator.getBattery();
return !battery.charging && battery.level <= MIN_BATTERY_LEVEL;
}

/**
* Checking whether a video can be played.
* This check is for IOS and checks if the power saving mode is enabled.
*
* In this case no video will be played automatically and play throws an error.
*/
export function canVideoPlay(blob) {
const video = document.createElement('video');
video.muted = true;
video.playsinline = true;
video.src = URL.createObjectURL(blob);
return video.play();
}
31 changes: 29 additions & 2 deletions src/tmpl/entry.tmpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ export default options => {
let code = `import { ${
options.performanceCheck ? `run, ` : ``
}hasSufficientPerformance, setup } from '#booster/utils/performance';
import { triggerRunCallback, observeBoosterButton, setupBoosterLayer, updateBoosterLayerMessage, initReducedView } from '#booster/utils/entry';
import { triggerRunCallback, observeBoosterButton, setupBoosterLayer, updateBoosterLayerMessage, initReducedView, hasBatteryPerformanceIssue } from '#booster/utils/entry';
import Deferred from '#booster/classes/Deferred';
import { isSupportedBrowser } from '#booster/utils/browser';
import {video as videoBlob} from './blobs.mjs';
`;

Expand Down Expand Up @@ -46,15 +47,38 @@ function client () {
const forceInit = ('__NUXT_BOOSTER_FORCE_INIT__' in window && window.__NUXT_BOOSTER_FORCE_INIT__);
async function initApp(force) {
if (initialized) {
deferred.resolve();
}
document.documentElement.classList.remove('nuxt-booster-reduced-view');
`;

if (!options.ignore.battery) {
code += `
try {
if (!force) {
await hasBatteryPerformanceIssue(videoBlob)
}
} catch (error) {
console.warn(error)
triggerRunCallback(false);
if (!!layerEl) {
// User must interact via the layer.
updateSpeedkitLayerMessage(layerEl, 'nuxt-speedkit-message-low-battery');
return null;
}
}
`;
}

`;
code += `
try {`;

if (options.performanceCheck) {
code += `
Expand All @@ -75,6 +99,9 @@ if (!force) {
deferred.resolve();
} catch (error) {
console.warn(error)
triggerRunCallback(false);
if (!!layerEl) {
Expand Down
22 changes: 22 additions & 0 deletions src/utils/blob.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { promises as fsPromises } from 'fs';
import mime from 'mime-types';

async function getFileInfo(name, file) {
return {
name,
// eslint-disable-next-line security/detect-non-literal-fs-filename
file: await fsPromises.readFile(file),
mimeType: mime.lookup(file)
};
}

export async function getTemplate(files) {
return (await Promise.all(files.map(file => getFileInfo(...file))))
.map(
({ name, file, mimeType }) =>
`export const ${name} = new Blob([new Uint8Array([${[...file].join(
', '
)}])], {type: '${mimeType}'});`
)
.join('\n');
}
3 changes: 2 additions & 1 deletion src/utils/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export function getDefaultOptions() {

detection: {
performance: true,
browserSupport: true
browserSupport: true,
battery: true
},

performanceMetrics: {
Expand Down

0 comments on commit 8e48dab

Please sign in to comment.