Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(entry): added battery level check #851

Merged
merged 23 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
643d417
fix(entry): added battery level check
ThornWalli Sep 11, 2023
b107660
Merge pull request #852 from GrabarzUndPartner/feature/module-improve…
ThornWalli Sep 12, 2023
bfef734
Merge pull request #853 from GrabarzUndPartner/next
ThornWalli Sep 12, 2023
2bf6714
chore(update): update from next
ThornWalli Sep 13, 2023
2b9206c
fix(entry): added video check (ios)
ThornWalli Sep 13, 2023
5d5332e
Merge commit '712347b0966ea473b86c33b62dabd91185fbe2e7' into feature/…
ThornWalli Sep 13, 2023
54ceb68
fix(entry): added ignore object
ThornWalli Sep 13, 2023
a3b9487
fix(entry): remove slient catches
ThornWalli Sep 21, 2023
2ac023e
fix(entry): remove try catch
ThornWalli Oct 10, 2023
a6f10fc
Merge branch 'next' into feature/entry-battery-level-check
ThornWalli Nov 13, 2023
9054d5b
fix(entry): added catch for video play
ThornWalli Nov 13, 2023
90a2f66
fix(entry): `hasBatteryPerformanceIssue` modified
ThornWalli Nov 14, 2023
565125b
fix(entry): reduce `isBatteryLow`
ThornWalli Nov 14, 2023
8da3062
Merge branch 'next' into feature/entry-battery-level-check
ThornWalli Nov 15, 2023
b2d7037
Merge branch 'next' into feature/entry-battery-level-check
ThornWalli Nov 18, 2023
74d6ae9
chore(update): update
ThornWalli Dec 24, 2023
6d47219
Merge branch 'next' into feature/entry-battery-level-check
ThornWalli Dec 27, 2023
388bfd8
Merge branch 'feature/renaming' into feature/entry-battery-level-check
ThornWalli Jan 12, 2024
a1f014f
Merge branch 'feature/renaming' into feature/entry-battery-level-check
ThornWalli Jan 12, 2024
2b3a45d
Merge branch 'feature/renaming' into feature/entry-battery-level-check
ThornWalli Feb 10, 2024
65c27a5
Merge branch 'feature/renaming' into feature/entry-battery-level-check
ThornWalli Apr 5, 2024
bcc5821
Merge branch 'feature/renaming' into feature/entry-battery-level-check
ThornWalli Apr 19, 2024
df17692
Merge branch 'main' into feature/entry-battery-level-check
ThornWalli Apr 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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-speedkit-message-unsupported-browser">outdated browser</li>
<li id="nuxt-speedkit-message-reduced-bandwidth">reduced-bandwidth</li>
<li id="nuxt-speedkit-message-weak-hardware">weak hardware</li>
<li id="nuxt-speedkit-message-low-battery">low battery</li>
</ul>
<div class="info-layer-buttons">
<base-button
Expand Down
Binary file added src/media/video.mp4
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we use an additional file? Or can we also use a super small base64 string?

Binary file not shown.
14 changes: 13 additions & 1 deletion src/module.mjs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it it helpful to create an ignore object? so we have an easy possibility to extend it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { optimizePreloads } from './utils/preload.mjs';
import { getSupportedBrowserDetector } from './utils/browser.mjs';
import { registerAppEntry as registerAppEntryWebpack } from './hookFunctions/webpack.mjs';
import { registerAppEntry as registerAppEntryVite } from './hookFunctions/vite.mjs';
import { getTemplate as getBlobFileTemplate } from './utils/blob.mjs';

const resolver = createResolver(import.meta.url);

Expand Down Expand Up @@ -143,11 +144,22 @@ 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
}
});

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
7 changes: 7 additions & 0 deletions src/runtime/components/SpeedkitLayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
</li>
<!-- Displayed when user hardware are not sufficient. -->
<li id="nuxt-speedkit-message-weak-hardware">weak hardware</li>

<!-- Displayed when the user batteries are not sufficient. -->
<li id="nuxt-speedkit-message-low-battery">low battery</li>
</ul>

<!-- Button to hide the layer with no javascript -->
Expand Down Expand Up @@ -98,5 +101,9 @@ useHead({
display: none;
}

#nuxt-speedkit-message-low-battery {
display: none;
}

/*! purgecss end ignore */
</style>
21 changes: 19 additions & 2 deletions src/runtime/tmpl/entry.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { <% if (options.performanceCheck) { %>run, <% } %>hasSufficientPerformance, setup } from '#speedkit/utils/performance';
import { triggerRunCallback, observeSpeedkitButton, setupSpeedkitLayer, updateSpeedkitLayerMessage, initReducedView } from '#speedkit/utils/entry';
import { triggerRunCallback, observeSpeedkitButton, setupSpeedkitLayer, updateSpeedkitLayerMessage, initReducedView, hasBatteryPerformanceIssue } from '#speedkit/utils/entry';
import Deferred from '#speedkit/classes/Deferred.mjs';
import { isSupportedBrowser } from '#speedkit/utils/browser';
import {video as videoBlob} from './blobs.mjs';

<% if (options.webpack) { %>
// webpack
Expand Down Expand Up @@ -35,14 +36,30 @@ function client () {
const forceInit = ('__NUXT_SPEEDKIT_FORCE_INIT__' in window && window.__NUXT_SPEEDKIT_FORCE_INIT__);

async function initApp(force) {

if (initialized) {
deferred.resolve();
}

document.documentElement.classList.remove('nuxt-speedkit-reduced-view');

<% if (!options.ignore.battery) { %>
try {
if (!force) {
await hasBatteryPerformanceIssue(videoBlob)
}
} catch (error) {
triggerRunCallback(false);

if (!!layerEl) {
// User must interact via the layer.
updateSpeedkitLayerMessage(layerEl, 'nuxt-speedkit-message-low-battery');
return null;
}
}
<% } %>

try {
<% if (options.performanceCheck) { %>if (!force) {
await run(<%= options.runOptions ? JSON.stringify(options.runOptions) : '' %>);
}<% } %>
Expand Down Expand Up @@ -78,7 +95,7 @@ function client () {

setup(<%= options.performanceMetrics %>);

if(('__NUXT_SPEEDKIT_AUTO_INIT__' in window && window.__NUXT_SPEEDKIT_AUTO_INIT__) || ((<%= !options.ignorePerformance %> && hasSufficientPerformance()) && supportedBrowser)) {
if(('__NUXT_SPEEDKIT_AUTO_INIT__' in window && window.__NUXT_SPEEDKIT_AUTO_INIT__) || ((<%= !options.ignore.performance %> && hasSufficientPerformance()) && supportedBrowser)) {
initApp();
} else {
setupSpeedkitLayer(layerEl, supportedBrowser)
Expand Down
54 changes: 54 additions & 0 deletions src/runtime/utils/entry.mjs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we implement a generalistic solution. so it also works on ios and in desktop browsers (laptop)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the silent catch to switch to video detection.

Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,57 @@ export function initReducedView() {
tmp.remove();
});
}

export async function hasBatteryPerformanceIssue(videoBlob) {
await isBatteryLow();
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;

try {
const battery = await window.navigator.getBattery();
if (!battery.charging && battery.level <= MIN_BATTERY_LEVEL) {
throw new Error('Battery is low.');
}
} catch (error) {
// Ignore Check
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

silent catch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unnecessary catch has been removed.

In the entry now console.warn are built in, these show the respective case as a warning.

image

}
}

/**
* 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.
*/
export async function canVideoPlay(blob) {
const VIDEO_TIMEOUT = 250;

const video = document.createElement('video');
video.muted = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need that. it seems to be a duplicate -> next line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All setAttribute have been removed and replaced with set properties.

video.setAttribute('muted', 'muted');
video.setAttribute('playsinline', 'playsinline');
video.src = URL.createObjectURL(blob);

const timeout = setTimeout(() => {
throw new Error('Video playback not possible. Reason: timeout');
}, VIDEO_TIMEOUT);

try {
await video.play();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explain me, what should happen here in combination with the timeout.
i think we should wait for the playing event? and perhaps there is another event we can use to detect it is not playing cause of weak battery

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Video timeout was removed.

Now only the reject from the video play() is caught.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play

clearTimeout(timeout);
} catch (error) {
clearTimeout(timeout);
throw new Error("Video playback not possible. Reason: can't play video");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please consign a meaningful error message

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then there is alternatively only the possibility to forward the video error.

No separate text for an error that we can not guess when a video does not play.

}
}
22 changes: 22 additions & 0 deletions src/utils/blob.mjs
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.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export function getDefaultOptions() {

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

performanceMetrics: {
Expand Down