Files
ThreadNet-Web/src/components/views/settings/notifications/NotificationSettings2.tsx
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

381 lines
17 KiB
TypeScript
Raw Normal View History

2023-06-29 17:46:31 +02:00
/*
2024-09-09 14:57:16 +01:00
Copyright 2024 New Vector Ltd.
2023-06-29 17:46:31 +02:00
Copyright 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
2024-09-09 14:57:16 +01:00
Please see LICENSE files in the repository root for full details.
2023-06-29 17:46:31 +02:00
*/
import React, { type JSX, useState } from "react";
import { SettingsToggleInput } from "@vector-im/compound-web";
2023-06-29 17:46:31 +02:00
import NewAndImprovedIcon from "../../../../../res/img/element-icons/new-and-improved.svg";
import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext";
import { useNotificationSettings } from "../../../../hooks/useNotificationSettings";
import { _t } from "../../../../languageHandler";
import {
DefaultNotificationSettings,
2025-02-05 13:25:06 +00:00
type NotificationSettings,
2023-06-29 17:46:31 +02:00
} from "../../../../models/notificationsettings/NotificationSettings";
import { RoomNotifState } from "../../../../RoomNotifs";
import { SettingLevel } from "../../../../settings/SettingLevel";
import { NotificationLevel } from "../../../../stores/notifications/NotificationLevel";
2023-06-29 17:46:31 +02:00
import { clearAllNotifications } from "../../../../utils/notifications";
import AccessibleButton from "../../elements/AccessibleButton";
2023-07-11 12:38:14 +02:00
import ExternalLink from "../../elements/ExternalLink";
2023-06-29 17:46:31 +02:00
import LabelledCheckbox from "../../elements/LabelledCheckbox";
import StyledRadioGroup from "../../elements/StyledRadioGroup";
import TagComposer from "../../elements/TagComposer";
import { StatelessNotificationBadge } from "../../rooms/NotificationBadge/StatelessNotificationBadge";
import { SettingsBanner } from "../shared/SettingsBanner";
import { SettingsSection } from "../shared/SettingsSection";
2024-11-05 18:36:26 +00:00
import { SettingsSubsection } from "../shared/SettingsSubsection";
2023-06-29 17:46:31 +02:00
import { NotificationPusherSettings } from "./NotificationPusherSettings";
2024-04-12 14:18:09 +01:00
import SettingsFlag from "../../elements/SettingsFlag";
import { SettingsSubsectionHeading } from "../shared/SettingsSubsectionHeading";
2023-06-29 17:46:31 +02:00
enum NotificationDefaultLevels {
AllMessages = "all_messages",
PeopleMentionsKeywords = "people_mentions_keywords",
MentionsKeywords = "mentions_keywords",
}
function toDefaultLevels(levels: NotificationSettings["defaultLevels"]): NotificationDefaultLevels {
if (levels.room === RoomNotifState.AllMessages) {
return NotificationDefaultLevels.AllMessages;
} else if (levels.dm === RoomNotifState.AllMessages) {
return NotificationDefaultLevels.PeopleMentionsKeywords;
} else {
return NotificationDefaultLevels.MentionsKeywords;
}
}
function boldText(text: string): JSX.Element {
return <strong>{text}</strong>;
}
2023-07-11 12:38:14 +02:00
function helpLink(sub: string): JSX.Element {
return <ExternalLink href="https://element.io/help#settings2">{sub}</ExternalLink>;
}
2023-06-29 17:46:31 +02:00
function useHasUnreadNotifications(): boolean {
const cli = useMatrixClientContext();
return cli.getRooms().some((room) => room.getUnreadNotificationCount() > 0);
}
2024-04-12 14:18:09 +01:00
/**
* The new notification settings tab view, only displayed if the user has Features.NotificationSettings2 enabled
*/
2023-06-29 17:46:31 +02:00
export default function NotificationSettings2(): JSX.Element {
const cli = useMatrixClientContext();
const { model, hasPendingChanges, reconcile } = useNotificationSettings(cli);
const disabled = model === null || hasPendingChanges;
const settings = model ?? DefaultNotificationSettings;
const [updatingUnread, setUpdatingUnread] = useState<boolean>(false);
const hasUnreadNotifications = useHasUnreadNotifications();
const NotificationOptions = [
{
value: NotificationDefaultLevels.AllMessages,
label: _t("notifications|all_messages"),
},
{
value: NotificationDefaultLevels.PeopleMentionsKeywords,
label: _t("settings|notifications|people_mentions_keywords"),
},
{
value: NotificationDefaultLevels.MentionsKeywords,
label: _t("settings|notifications|mentions_keywords_only"),
},
];
2023-06-29 17:46:31 +02:00
return (
<div className="mx_NotificationSettings2">
{hasPendingChanges && model !== null && (
<SettingsBanner
icon={<img src={NewAndImprovedIcon} alt="" width={12} />}
action={_t("action|proceed")}
2023-06-29 17:46:31 +02:00
onAction={() => reconcile(model!)}
>
{_t(
"settings|notifications|labs_notice_prompt",
2023-06-29 17:46:31 +02:00
{},
2023-07-11 12:38:14 +02:00
{
strong: boldText,
a: helpLink,
},
2023-06-29 17:46:31 +02:00
)}
</SettingsBanner>
)}
<SettingsSection>
2023-06-29 17:46:31 +02:00
<div className="mx_SettingsSubsection_content mx_NotificationSettings2_flags">
<SettingsToggleInput
name="enable_notifications_account"
label={_t("settings|notifications|enable_notifications_account")}
checked={!settings.globalMute}
2023-06-29 17:46:31 +02:00
disabled={disabled}
onChange={(evt) => {
2023-06-29 17:46:31 +02:00
reconcile({
...model!,
globalMute: !evt.target.checked,
2023-06-29 17:46:31 +02:00
});
}}
/>
<SettingsFlag name="notificationsEnabled" level={SettingLevel.DEVICE} />
<SettingsFlag
name="notificationBodyEnabled"
label={_t("settings|notifications|desktop_notification_message_preview")}
level={SettingLevel.DEVICE}
2023-06-29 17:46:31 +02:00
/>
<SettingsFlag name="audioNotificationsEnabled" level={SettingLevel.DEVICE} />
2023-06-29 17:46:31 +02:00
</div>
<SettingsSubsection
heading={
<SettingsSubsectionHeading
heading={_t("settings|notifications|default_setting_section")}
as="h2"
/>
}
description={_t("settings|notifications|default_setting_description")}
2023-06-29 17:46:31 +02:00
>
<StyledRadioGroup
name="defaultNotificationLevel"
value={toDefaultLevels(settings.defaultLevels)}
disabled={disabled}
definitions={NotificationOptions}
onChange={(value) => {
reconcile({
...model!,
defaultLevels: {
...model!.defaultLevels,
dm:
value !== NotificationDefaultLevels.MentionsKeywords
? RoomNotifState.AllMessages
: RoomNotifState.MentionsOnly,
room:
value === NotificationDefaultLevels.AllMessages
? RoomNotifState.AllMessages
: RoomNotifState.MentionsOnly,
},
});
}}
/>
</SettingsSubsection>
<SettingsSubsection
heading={
<SettingsSubsectionHeading
heading={_t("settings|notifications|play_sound_for_section")}
as="h2"
/>
}
description={_t("settings|notifications|play_sound_for_description")}
2023-06-29 17:46:31 +02:00
>
<LabelledCheckbox
label={_t("common|people")}
2023-06-29 17:46:31 +02:00
value={settings.sound.people !== undefined}
disabled={disabled || settings.defaultLevels.dm === RoomNotifState.MentionsOnly}
2023-06-29 17:46:31 +02:00
onChange={(value) => {
reconcile({
...model!,
sound: {
...model!.sound,
people: value ? "default" : undefined,
},
});
}}
/>
<LabelledCheckbox
label={_t("settings|notifications|mentions_keywords")}
2023-06-29 17:46:31 +02:00
value={settings.sound.mentions !== undefined}
disabled={disabled}
onChange={(value) => {
reconcile({
...model!,
sound: {
...model!.sound,
mentions: value ? "default" : undefined,
},
});
}}
/>
<LabelledCheckbox
label={_t("settings|notifications|voip")}
2023-06-29 17:46:31 +02:00
value={settings.sound.calls !== undefined}
disabled={disabled}
onChange={(value) => {
reconcile({
...model!,
sound: {
...model!.sound,
calls: value ? "ring" : undefined,
},
});
}}
/>
</SettingsSubsection>
<SettingsSubsection
heading={<SettingsSubsectionHeading heading={_t("settings|notifications|other_section")} as="h2" />}
>
2023-06-29 17:46:31 +02:00
<LabelledCheckbox
label={_t("settings|notifications|invites")}
2023-06-29 17:46:31 +02:00
value={settings.activity.invite}
disabled={disabled}
onChange={(value) => {
reconcile({
...model!,
activity: {
...model!.activity,
invite: value,
},
});
}}
/>
<LabelledCheckbox
label={_t("settings|notifications|room_activity")}
2023-06-29 17:46:31 +02:00
value={settings.activity.status_event}
disabled={disabled}
onChange={(value) => {
reconcile({
...model!,
activity: {
...model!.activity,
status_event: value,
},
});
}}
/>
<LabelledCheckbox
label={_t("settings|notifications|notices")}
2023-06-29 17:46:31 +02:00
value={settings.activity.bot_notices}
disabled={disabled}
onChange={(value) => {
reconcile({
...model!,
activity: {
...model!.activity,
bot_notices: value,
},
});
}}
/>
</SettingsSubsection>
<SettingsSubsection
heading={
<SettingsSubsectionHeading heading={_t("settings|notifications|mentions_keywords")} as="h2" />
}
2023-06-29 17:46:31 +02:00
description={_t(
"settings|notifications|keywords",
2023-06-29 17:46:31 +02:00
{},
{
badge: (
<StatelessNotificationBadge
symbol="1"
count={1}
level={NotificationLevel.Notification}
/>
),
2023-06-29 17:46:31 +02:00
},
)}
>
<LabelledCheckbox
label={_t("settings|notifications|notify_at_room")}
2023-06-29 17:46:31 +02:00
value={settings.mentions.room}
disabled={disabled}
onChange={(value) => {
reconcile({
...model!,
mentions: {
...model!.mentions,
room: value,
},
});
}}
/>
<LabelledCheckbox
label={_t("settings|notifications|notify_mention", {
2023-06-29 17:46:31 +02:00
mxid: cli.getUserId()!,
})}
id="mx_NotificationSettings2_MentionCheckbox"
2023-06-29 17:46:31 +02:00
value={settings.mentions.user}
disabled={disabled}
onChange={(value) => {
reconcile({
...model!,
mentions: {
...model!.mentions,
user: value,
},
});
}}
/>
<LabelledCheckbox
label={_t("settings|notifications|notify_keyword")}
byline={_t("settings|notifications|keywords_prompt")}
2023-06-29 17:46:31 +02:00
value={settings.mentions.keywords}
disabled={disabled}
onChange={(value) => {
reconcile({
...model!,
mentions: {
...model!.mentions,
keywords: value,
},
});
}}
/>
<TagComposer
id="mx_NotificationSettings2_Keywords"
tags={model?.keywords ?? []}
disabled={disabled}
onAdd={(keyword) => {
reconcile({
...model!,
keywords: [keyword, ...model!.keywords],
});
}}
onRemove={(keyword) => {
reconcile({
...model!,
keywords: model!.keywords.filter((it) => it !== keyword),
});
}}
label={_t("notifications|keyword")}
placeholder={_t("notifications|keyword_new")}
2023-06-29 17:46:31 +02:00
/>
2024-04-12 14:18:09 +01:00
<SettingsFlag name="Notifications.showbold" level={SettingLevel.DEVICE} />
<SettingsFlag name="Notifications.tac_only_notifications" level={SettingLevel.DEVICE} />
2023-06-29 17:46:31 +02:00
</SettingsSubsection>
<NotificationPusherSettings />
<SettingsSubsection heading={_t("settings|notifications|quick_actions_section")}>
2023-06-29 17:46:31 +02:00
{hasUnreadNotifications && (
<AccessibleButton
kind="primary_outline"
disabled={updatingUnread}
onClick={async () => {
setUpdatingUnread(true);
await clearAllNotifications(cli);
setUpdatingUnread(false);
}}
>
{_t("settings|notifications|quick_actions_mark_all_read")}
2023-06-29 17:46:31 +02:00
</AccessibleButton>
)}
<AccessibleButton
kind="danger_outline"
disabled={model === null}
onClick={() => {
reconcile(DefaultNotificationSettings);
}}
>
{_t("settings|notifications|quick_actions_reset")}
2023-06-29 17:46:31 +02:00
</AccessibleButton>
</SettingsSubsection>
</SettingsSection>
</div>
);
}