Notifications: Permanent option and close button (#563)
Co-authored-by: Ven <vendicated@riseup.net>
This commit is contained in:
parent
cab72e1be6
commit
e219aaa062
3 changed files with 58 additions and 10 deletions
|
@ -20,7 +20,7 @@ import "./styles.css";
|
||||||
|
|
||||||
import { useSettings } from "@api/settings";
|
import { useSettings } from "@api/settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Forms, React, useEffect, useMemo, useState, useStateFromStores, WindowStore } from "@webpack/common";
|
import { React, useEffect, useMemo, useState, useStateFromStores, WindowStore } from "@webpack/common";
|
||||||
|
|
||||||
import { NotificationData } from "./Notifications";
|
import { NotificationData } from "./Notifications";
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@ export default ErrorBoundary.wrap(function NotificationComponent({
|
||||||
icon,
|
icon,
|
||||||
onClick,
|
onClick,
|
||||||
onClose,
|
onClose,
|
||||||
image
|
image,
|
||||||
|
permanent
|
||||||
}: NotificationData) {
|
}: NotificationData) {
|
||||||
const { timeout, position } = useSettings(["notifications.timeout", "notifications.position"]).notifications;
|
const { timeout, position } = useSettings(["notifications.timeout", "notifications.position"]).notifications;
|
||||||
const hasFocus = useStateFromStores([WindowStore], () => WindowStore.isFocused());
|
const hasFocus = useStateFromStores([WindowStore], () => WindowStore.isFocused());
|
||||||
|
@ -43,7 +44,7 @@ export default ErrorBoundary.wrap(function NotificationComponent({
|
||||||
const start = useMemo(() => Date.now(), [timeout, isHover, hasFocus]);
|
const start = useMemo(() => Date.now(), [timeout, isHover, hasFocus]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isHover || !hasFocus || timeout === 0) return void setElapsed(0);
|
if (isHover || !hasFocus || timeout === 0 || permanent) return void setElapsed(0);
|
||||||
|
|
||||||
const intervalId = setInterval(() => {
|
const intervalId = setInterval(() => {
|
||||||
const elapsed = Date.now() - start;
|
const elapsed = Date.now() - start;
|
||||||
|
@ -74,14 +75,36 @@ export default ErrorBoundary.wrap(function NotificationComponent({
|
||||||
<div className="vc-notification">
|
<div className="vc-notification">
|
||||||
{icon && <img className="vc-notification-icon" src={icon} alt="" />}
|
{icon && <img className="vc-notification-icon" src={icon} alt="" />}
|
||||||
<div className="vc-notification-content">
|
<div className="vc-notification-content">
|
||||||
<Forms.FormTitle tag="h2">{title}</Forms.FormTitle>
|
<div className="vc-notification-header">
|
||||||
|
<h2 className="vc-notification-title">{title}</h2>
|
||||||
|
<button
|
||||||
|
style={{ all: "unset", cursor: "pointer" }}
|
||||||
|
onClick={e => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
onClose!();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="vc-notification-close-btn"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
role="img"
|
||||||
|
aria-labelledby="vc-notification-dismiss-title"
|
||||||
|
>
|
||||||
|
<title id="vc-notification-dismiss-title">Dismiss Notification</title>
|
||||||
|
<path fill="currentColor" d="M18.4 4L12 10.4L5.6 4L4 5.6L10.4 12L4 18.4L5.6 20L12 13.6L18.4 20L20 18.4L13.6 12L20 5.6L18.4 4Z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{richBody ?? <p className="vc-notification-p">{body}</p>}
|
{richBody ?? <p className="vc-notification-p">{body}</p>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{image && <img className="vc-notification-img" src={image} alt="" />}
|
{image && <img className="vc-notification-img" src={image} alt="" />}
|
||||||
{timeout !== 0 && (
|
{timeout !== 0 && !permanent && (
|
||||||
<div
|
<div
|
||||||
className="vc-notification-progressbar"
|
className="vc-notification-progressbar"
|
||||||
style={{ width: `${(1 - timeoutProgress) * 100}%`, backgroundColor: color || "var(--brand-experiment)" }}
|
style={{ width: `${(1 - timeoutProgress) * 100}%`, backgroundColor: color || "var(--brand-experiment)" }}
|
||||||
|
|
|
@ -54,6 +54,8 @@ export interface NotificationData {
|
||||||
onClick?(): void;
|
onClick?(): void;
|
||||||
onClose?(): void;
|
onClose?(): void;
|
||||||
color?: string;
|
color?: string;
|
||||||
|
/** Whether this notification should not have a timeout */
|
||||||
|
permanent?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _showNotification(notification: NotificationData, id: number) {
|
function _showNotification(notification: NotificationData, id: number) {
|
||||||
|
|
|
@ -22,17 +22,40 @@
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vc-notification-content {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-notification-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-notification-title {
|
||||||
|
color: var(--header-primary);
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-notification-close-btn {
|
||||||
|
color: var(--interactive-normal);
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: opacity 0.2s ease-in-out, color 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-notification-close-btn:hover {
|
||||||
|
color: var(--interactive-hover);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.vc-notification-icon {
|
.vc-notification-icon {
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discord adding 3km margin to generic tags */
|
|
||||||
.vc-notification h2 {
|
|
||||||
margin: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vc-notification-progressbar {
|
.vc-notification-progressbar {
|
||||||
height: 0.25rem;
|
height: 0.25rem;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
Loading…
Reference in a new issue