Battery api provide an easy way to handle battery status in browser.
Battery api can provide you following information:-
Battery charging level between
0.00 to 1.00
in decimal number. You can easily convert this decimal number into percentage by multiplying with100
.Charging or Discharging boolean status
Charging time in seconds
Discharging time in seconds
SolidJS
Solid is a declarative JavaScript library for creating user interfaces. It does not use a Virtual DOM. Instead it opts to compile its templates down to real DOM nodes and wrap updates in fine grained reactions. This way when your state updates only the code that depends on it runs.
SolidJS Documentation
Init new Solidjs project from Javascript template
> npx degit solidjs/templates/js my-app
> cd my-app
> pnpm i
> pnpm run dev
Install Hope UI
pnpm add @hope-ui/solid @stitches/core solid-transition-group
Open the project in vscode
code .
Lets start code by building a useBattery
hook . This hook will call web battery api and listen for battery event and update the store state
> mkdir hooks
> cd hooks
> touch useBattery.jsx
useBattery.jsx
import { onMount } from "solid-js";
import { createStore } from "solid-js/store";
export default function useBattery() {
const [store, setStore] = createStore({
isSupported: true,
charging: false,
chargingTime: 0,
dischargingTime: 0,
level: 0,
});
onMount(async () => {
try {
const battery = await navigator.getBattery();
console.log(battery);
updateAllBatteryInfo(battery);
battery.addEventListener("chargingchange", () => {
updateChargeInfo(battery);
});
battery.addEventListener("levelchange", () => {
updateLevelInfo(battery);
});
battery.addEventListener("chargingtimechange", () => {
updateChargingInfo(battery);
});
battery.addEventListener("dischargingtimechange", () => {
updateDischargingInfo(battery);
});
} catch (error) {
console.log(error);
setStore("isSupported", false);
}
});
function updateAllBatteryInfo(battery) {
updateChargeInfo(battery);
updateLevelInfo(battery);
updateChargingInfo(battery);
updateDischargingInfo(battery);
}
function updateChargeInfo(battery) {
setStore("charging", battery.charging);
}
function updateLevelInfo(battery) {
setStore("level", battery.level);
}
function updateChargingInfo(battery) {
setStore("chargingTime", battery.chargingTime);
}
function updateDischargingInfo(battery) {
setStore("dischargingTime", battery.dischargingTime);
}
return {
store,
};
}
onMount
is a lifecycle function in solidjs which run only once when component mount you can run side effect inside this function like api call. We use this function to add event listener for battery event and initialise store with initial value provided by battery api.
The createStore
call takes the initial value (here we provide battery related fields) and returns a read/write tuple. The first element is the store proxy which is readonly, and the second is a setter function.
navigator.getBattery()
call web battery api and return promise this resolves to BatteryManager
Object contains information about charging level, charging time etc...
If browser does not support battery web api then catch block will execute and it update isSupported
to false and on ui screen we can show alert box.
BatteryManager
Object during discharging
{
charging: false
chargingTime: Infinity
dischargingTime: 13684
level: 0.62
}
chargingchange
event fired when you connect or disconnect your device from charger.
levelchange
event fired when your device battery level change. Suppose your device is charging and their level change from 0.79 to 0.80 then this event will fired.
chargingtimechange
event fired when battery charging time will updated
dischargingtimechange
fired when battery discharging time will updated.
Lets build the ui to show the battery related data in App.js
import {
Alert,
AlertDescription,
AlertIcon,
AlertTitle,
Box,
CircularProgress,
CircularProgressIndicator,
CircularProgressLabel,
Container,
GridItem,
Heading,
HopeProvider,
HStack,
SimpleGrid,
Tag,
Text,
VStack,
} from "@hope-ui/solid";
import { Show } from "solid-js";
import ThemeSwitcher from "./components/ThemeSwitcher";
import useBattery from "./hooks/useBattery";
export default function App() {
const { store } = useBattery();
return (
<HopeProvider config={{ initialColorMode: "dark" }}>
<Box minH={"100vh"} h="$full" w={"$full"} py="$10">
<VStack spacing={"$3"}>
<Heading textAlign={"center"} fontSize={"$6xl"}>
Battery
<Box as="span" color={"$primary10"}>
Monitor
</Box>
</Heading>
<HStack spacing={"$2"}>
<Show when={store.isSupported}>
<Tag
colorScheme={store.charging ? "success" : "danger"}
size={"lg"}
variant="dot"
dotPlacement="start"
>
<Show when={store.charging} fallback="Discharging">
Charging
</Show>
</Tag>
</Show>
<ThemeSwitcher />
</HStack>
</VStack>
<Container mt={"$10"}>
<Show
when={store.isSupported}
fallback={
<Alert
status="danger"
variant="subtle"
flexDirection="column"
justifyContent="center"
textAlign="center"
height="200px"
>
<AlertIcon boxSize="40px" mr="0" />
<AlertTitle mt="$4" mb="$1" fontSize="$lg">
Unsupported Browser
</AlertTitle>
<AlertDescription maxWidth="$sm">
Your browser does not support Web Battery API
</AlertDescription>
</Alert>
}
>
<SimpleGrid
w={"$full"}
columns={{ "@initial": 1, "@sm": 2, "@md": 3 }}
justifyContent="center"
>
<GridItem mx={"auto"}>
<CircularProgress thickness={"$0_5"} size={"$xs"} value={100}>
<CircularProgressIndicator color={"$warning10"} />
<CircularProgressLabel>
<VStack spacing={"$6"}>
<Heading fontSize={"$xl"}> Charging Time</Heading>
<Text fontSize={"$xl"}>
{Math.round(store.chargingTime / 60)} Minutes
</Text>
</VStack>
</CircularProgressLabel>
</CircularProgress>
</GridItem>
<GridItem mx={"auto"}>
<CircularProgress size={"$xs"} value={store.level * 100}>
<CircularProgressIndicator color={"$success10"} />
<CircularProgressLabel>
<VStack spacing={"$6"}>
<Heading fontSize={"$xl"}> Battery Level</Heading>
<Text fontSize={"$xl"}>{store.level * 100} %</Text>
</VStack>
</CircularProgressLabel>
</CircularProgress>
</GridItem>
<GridItem mx={"auto"}>
<CircularProgress thickness={"$0_5"} size={"$xs"} value={100}>
<CircularProgressIndicator color={"$primary10"} />
<CircularProgressLabel>
<VStack spacing={"$6"}>
<Heading fontSize={"$xl"}> Discharging Time</Heading>
<Text fontSize={"$xl"}>
{Math.round(store.dischargingTime / 60)} Minutes
</Text>
</VStack>
</CircularProgressLabel>
</CircularProgress>
</GridItem>
</SimpleGrid>
</Show>
</Container>
</Box>
</HopeProvider>
);
}
ThemeSwitcher.jsx
component handle switching between dark and light mode.
import { Button, useColorMode } from "@hope-ui/solid";
export default function ThemeSwitcher() {
const { colorMode, toggleColorMode } = useColorMode();
return (
<Button
rounded={"$full"}
size="sm"
colorScheme={"warning"}
onClick={toggleColorMode}
>
{colorMode() === "light" ? "Light" : "Dark"} mode
</Button>
);
}
harshmangalam / solidjs-web-battery-monitor
Web battery monitor using Solidjs
Usage
Those templates dependencies are maintained via pnpm via pnpm up -Lri
.
This is the reason you see a pnpm-lock.yaml
. That being said, any package manager will work. This file can be safely be removed once you clone a template.
$ npm install # or pnpm install or yarn install
Learn more on the Solid Website and come chat with us on our Discord
Available Scripts
In the project directory, you can run:
npm dev
or npm start
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
npm run build
Builds the app for production to the dist
folder.
It correctly bundles Solid in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
Deployment
You canβ¦
Top comments (2)
Nice work, one comment though, you should add an onCleanup to remove the registered events. :-)
Thanks @davedbase i have updated my repo with cleanup events code.