From 06a1d71739b356da8b201da7718a023fd5d4fbb3 Mon Sep 17 00:00:00 2001 From: Blankeos Date: Sun, 6 Oct 2024 00:09:26 +0800 Subject: [PATCH] feat: Added use-network. --- README.md | 2 +- dev/App.tsx | 7 +++- src/index.ts | 1 + src/use-network/use-network.ts | 75 ++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/use-network/use-network.ts diff --git a/README.md b/README.md index 30c581b..5c777ca 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Based on the [@mantine/hooks](https://github.com/mantinedev/mantine/tree/master/ - [ ] use-mouse - [ ] use-move - [ ] use-mutation-observer -- [ ] use-network +- [x] use-network - [ ] use-orientation - [x] use-os - [ ] use-page-leave diff --git a/dev/App.tsx b/dev/App.tsx index 402c7c8..53a1304 100644 --- a/dev/App.tsx +++ b/dev/App.tsx @@ -2,7 +2,7 @@ import type { Component } from 'solid-js'; import './app.css'; // Hooks -import { useClickOutside, useHotkeys, useHover, useIdle, useOs } from '../src'; +import { useClickOutside, useHotkeys, useHover, useIdle, useNetwork, useOs } from '../src'; const App: Component = () => { // let ref = useClickOutside(() => { @@ -17,6 +17,9 @@ const App: Component = () => { events: ['mousemove', 'touchmove'], initialState: false, }); + + const networkStatus = useNetwork(); + return (
{/*

@@ -28,6 +31,8 @@ const App: Component = () => {

hovered: {JSON.stringify(hovered())}

idle: {JSON.stringify(idle())}

+ +

networkStatus: {JSON.stringify(networkStatus())}

); }; diff --git a/src/index.ts b/src/index.ts index 60a18ef..392b9a8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,4 +3,5 @@ export * from './use-hotkeys/use-hotkeys'; export * from './use-hover/use-hover'; export * from './use-idle/use-idle'; export * from './use-mounted/use-mounted'; +export * from './use-network/use-network'; export * from './use-os/use-os'; diff --git a/src/use-network/use-network.ts b/src/use-network/use-network.ts new file mode 100644 index 0000000..6476f05 --- /dev/null +++ b/src/use-network/use-network.ts @@ -0,0 +1,75 @@ +import { createEffect, createSignal, onCleanup, onMount } from 'solid-js'; + +interface NetworkStatus { + downlink?: number; + downlinkMax?: number; + effectiveType?: 'slow-2g' | '2g' | '3g' | '4g'; + rtt?: number; + saveData?: boolean; + type?: 'bluetooth' | 'cellular' | 'ethernet' | 'wifi' | 'wimax' | 'none' | 'other' | 'unknown'; +} + +function getConnection(): NetworkStatus { + if (typeof navigator === 'undefined') { + return {}; + } + + const _navigator = navigator as any; + const connection: any = + _navigator.connection || _navigator.mozConnection || _navigator.webkitConnection; + + if (!connection) { + return {}; + } + + return { + downlink: connection?.downlink, + downlinkMax: connection?.downlinkMax, + effectiveType: connection?.effectiveType, + rtt: connection?.rtt, + saveData: connection?.saveData, + type: connection?.type, + }; +} + +/** + * A hook that returns the current network status. + */ +export function useNetwork() { + const [status, setStatus] = createSignal<{ online: boolean } & NetworkStatus>({ + online: true, + }); + + function handleConnectionChange() { + setStatus(current => ({ ...current, ...getConnection() })); + } + + onMount(() => { + const onlineListener = () => setStatus({ online: true, ...getConnection() }); + const offlineListener = () => setStatus({ online: false, ...getConnection() }); + window.addEventListener('offline', offlineListener); + + onCleanup(() => { + window.removeEventListener('online', onlineListener); + window.removeEventListener('offline', offlineListener); + }); + }); + + createEffect(() => { + const _navigator = navigator as any; + + if (_navigator.connection) { + setStatus({ online: _navigator.onLine, ...getConnection() }); + _navigator.connection.addEventListener('change', handleConnectionChange); + + onCleanup(() => _navigator.connection.removeEventListener('change', handleConnectionChange)); + } + + if (typeof _navigator.onLine === 'boolean') { + // Required for Firefox and other browsers that don't support navigator.connection + setStatus(current => ({ ...current, online: _navigator.onLine })); + } + }); + + return status; +}