Skip to content

Commit

Permalink
feat: useWebNotification (#62)
Browse files Browse the repository at this point in the history
* feat: add useWebNotification
  • Loading branch information
childrentime authored Oct 7, 2023
1 parent 716cf08 commit e5d4b58
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 207 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@babel/preset-typescript": "^7.18.6",
"@babel/runtime-corejs3": "^7.20.1",
"@reactuses/core": "workspace:*",
"@ririd/eslint-config": "0.6.0",
"@ririd/eslint-config": "0.7.0",
"@types/fs-extra": "^9.0.13",
"@types/node": "^18.16.6",
"@types/prompts": "^2.4.4",
Expand All @@ -41,7 +41,7 @@
"@typescript-eslint/parser": "^5.59.6",
"chalk": "4.1.2",
"cross-env": "^7.0.3",
"eslint": "^8.48.0",
"eslint": "^8.51.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"esno": "^0.16.3",
Expand Down
3 changes: 3 additions & 0 deletions packages/core/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ import useMeasure from "./useMeasure";
import useHover from "./useHover";
import useScreenSafeArea from "./useScreenSafeArea";
import useCssVar from "./useCssVar";
import useWebNotification from "./useWebNotification";

export {
usePrevious,
Expand Down Expand Up @@ -185,6 +186,7 @@ export {
useHover,
useScreenSafeArea,
useCssVar,
useWebNotification,
};

export * from "./useToggle";
Expand Down Expand Up @@ -279,3 +281,4 @@ export * from "./useMeasure";
export * from "./useHover";
export * from "./useScreenSafeArea";
export * from "./useCssVar";
export * from "./useWebNotification";
7 changes: 7 additions & 0 deletions packages/core/hooks/useWebNotification/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# useWebNotification

The Web Notification interface of the Notifications API is used to configure and display desktop notifications to the user.

::: warning
Attention: For users on the Mac system, it is necessary for them to have enabled notifications for Chrome in their system settings. Without enabling notifications for Chrome in the system, even if the front-end page requests permission, notifications will not be displayed.
:::
27 changes: 27 additions & 0 deletions packages/core/hooks/useWebNotification/demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import useWebNotification from ".";

export default function Demo() {
const { isSupported, show, close }
= useWebNotification(true);
return (
<div>
<p>Supported: {JSON.stringify(isSupported)}</p>
{isSupported
? (
<div>
<button
onClick={() => {
show("Hello, world from ReactUse!");
}}
>
Show Notification
</button>
<button onClick={close}>Close</button>
</div>
)
: (
<div>The Notification Web API is not supported in your browser.</div>
)}
</div>
);
}
7 changes: 7 additions & 0 deletions packages/core/hooks/useWebNotification/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import useWebNotification from ".";

describe("useWebNotification", () => {
it("should be defined", () => {
expect(useWebNotification).toBeDefined();
});
});
69 changes: 69 additions & 0 deletions packages/core/hooks/useWebNotification/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { useCallback, useEffect, useRef } from "react";
import useSupported from "../useSupported";
import useUnmount from "../useUnmount";
import { defaultOptions } from "../utils/defaults";

export default function useWebNotification(requestPermissions = false) {
const isSupported = useSupported(() => !!window && "Notification" in window);
const permissionGranted = useRef(false);

const notificationRef = useRef<Notification | null>(null);

const show = (
title: string,
options: NotificationOptions = defaultOptions,
) => {
// If either the browser does not support notifications or the user has
// not granted permission, do nothing:
if (!isSupported && !permissionGranted.current) {
return;
}

notificationRef.current = new Notification(title || "", options);
return notificationRef.current;
};

const close = useCallback((): void => {
if (notificationRef.current) {
notificationRef.current.close();
}

notificationRef.current = null;
}, []);

useEffect(() => {
permissionGranted.current
= isSupported
&& "permission" in Notification
&& Notification.permission === "granted";
}, [isSupported]);

const ensurePermissions = useCallback(async () => {
if (!isSupported)
return;

if (!permissionGranted.current && Notification.permission !== "denied") {
const result = await Notification.requestPermission();
if (result === "granted")
permissionGranted.current = true;
}

return permissionGranted.current;
}, [isSupported]);

useEffect(() => {
if (requestPermissions) {
ensurePermissions();
}
}, [requestPermissions, ensurePermissions]);

useUnmount(close);

return {
isSupported,
show,
close,
ensurePermissions,
permissionGranted,
} as const;
}
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"./package.json": "./package.json",
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.cjs",
"import": "./dist/index.mjs"
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"main": "./dist/index.cjs",
Expand Down
3 changes: 2 additions & 1 deletion packages/website/src/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@
"useClipboard",
"useEyeDropper",
"useScreenSafeArea",
"useCssVar"
"useCssVar",
"useWebNotification"
]
}
]
Expand Down
Loading

0 comments on commit e5d4b58

Please sign in to comment.