mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-29 10:20:59 -05:00
feat(mobx): server notification options + data store
This commit is contained in:
parent
f8b8d96d3d
commit
413bf6949b
10 changed files with 237 additions and 102 deletions
|
@ -117,7 +117,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-muted="true"] {
|
&[data-muted="true"] {
|
||||||
color: var(--tertiary-foreground);
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-alert="true"],
|
&[data-alert="true"],
|
||||||
|
|
|
@ -199,7 +199,7 @@ interface Props {
|
||||||
|
|
||||||
export const ServerListSidebar = observer(({ unreads }: Props) => {
|
export const ServerListSidebar = observer(({ unreads }: Props) => {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const layout = useApplicationState().layout;
|
const state = useApplicationState();
|
||||||
|
|
||||||
const { server: server_id } = useParams<{ server?: string }>();
|
const { server: server_id } = useParams<{ server?: string }>();
|
||||||
const server = server_id ? client.servers.get(server_id) : undefined;
|
const server = server_id ? client.servers.get(server_id) : undefined;
|
||||||
|
@ -210,6 +210,7 @@ export const ServerListSidebar = observer(({ unreads }: Props) => {
|
||||||
|
|
||||||
const unreadChannels = channels
|
const unreadChannels = channels
|
||||||
.filter((x) => x.unread)
|
.filter((x) => x.unread)
|
||||||
|
.filter((x) => !state.notifications.isMuted(x.channel))
|
||||||
.map((x) => x.channel?._id);
|
.map((x) => x.channel?._id);
|
||||||
|
|
||||||
const servers = activeServers.map((server) => {
|
const servers = activeServers.map((server) => {
|
||||||
|
@ -268,7 +269,7 @@ export const ServerListSidebar = observer(({ unreads }: Props) => {
|
||||||
<ServerList>
|
<ServerList>
|
||||||
<ConditionalLink
|
<ConditionalLink
|
||||||
active={homeActive}
|
active={homeActive}
|
||||||
to={layout.getLastHomePath()}>
|
to={state.layout.getLastHomePath()}>
|
||||||
<ServerEntry home active={homeActive}>
|
<ServerEntry home active={homeActive}>
|
||||||
<Swoosh />
|
<Swoosh />
|
||||||
<div
|
<div
|
||||||
|
@ -300,7 +301,7 @@ export const ServerListSidebar = observer(({ unreads }: Props) => {
|
||||||
<ConditionalLink
|
<ConditionalLink
|
||||||
key={entry.server._id}
|
key={entry.server._id}
|
||||||
active={active}
|
active={active}
|
||||||
to={layout.getServerPath(entry.server._id)}>
|
to={state.layout.getServerPath(entry.server._id)}>
|
||||||
<ServerEntry
|
<ServerEntry
|
||||||
active={active}
|
active={active}
|
||||||
onContextMenu={attachContextMenu("Menu", {
|
onContextMenu={attachContextMenu("Menu", {
|
||||||
|
|
|
@ -28,7 +28,6 @@ import ConnectionStatus from "../items/ConnectionStatus";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
unreads: Unreads;
|
unreads: Unreads;
|
||||||
notifications: Notifications;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ServerBase = styled.div`
|
const ServerBase = styled.div`
|
||||||
|
@ -59,7 +58,7 @@ const ServerList = styled.div`
|
||||||
|
|
||||||
const ServerSidebar = observer((props: Props) => {
|
const ServerSidebar = observer((props: Props) => {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const layout = useApplicationState().layout;
|
const state = useApplicationState();
|
||||||
const { server: server_id, channel: channel_id } =
|
const { server: server_id, channel: channel_id } =
|
||||||
useParams<{ server: string; channel?: string }>();
|
useParams<{ server: string; channel?: string }>();
|
||||||
|
|
||||||
|
@ -85,7 +84,7 @@ const ServerSidebar = observer((props: Props) => {
|
||||||
if (!channel_id) return;
|
if (!channel_id) return;
|
||||||
if (!server_id) return;
|
if (!server_id) return;
|
||||||
|
|
||||||
layout.setLastOpened(server_id, channel_id);
|
state.layout.setLastOpened(server_id, channel_id);
|
||||||
}, [channel_id, server_id]);
|
}, [channel_id, server_id]);
|
||||||
|
|
||||||
const uncategorised = new Set(server.channel_ids);
|
const uncategorised = new Set(server.channel_ids);
|
||||||
|
@ -96,7 +95,6 @@ const ServerSidebar = observer((props: Props) => {
|
||||||
if (!entry) return;
|
if (!entry) return;
|
||||||
|
|
||||||
const active = channel?._id === entry._id;
|
const active = channel?._id === entry._id;
|
||||||
const muted = props.notifications[id] === "none";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConditionalLink
|
<ConditionalLink
|
||||||
|
@ -120,7 +118,7 @@ const ServerSidebar = observer((props: Props) => {
|
||||||
// ! FIXME: pull it out directly
|
// ! FIXME: pull it out directly
|
||||||
alert={mapChannelWithUnread(entry, props.unreads).unread}
|
alert={mapChannelWithUnread(entry, props.unreads).unread}
|
||||||
compact
|
compact
|
||||||
muted={muted}
|
muted={state.notifications.isMuted(entry)}
|
||||||
/>
|
/>
|
||||||
</ConditionalLink>
|
</ConditionalLink>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { useCallback, useContext, useEffect } from "preact/hooks";
|
||||||
|
|
||||||
import { useTranslation } from "../../lib/i18n";
|
import { useTranslation } from "../../lib/i18n";
|
||||||
|
|
||||||
|
import { useApplicationState } from "../../mobx/State";
|
||||||
import { connectState } from "../../redux/connector";
|
import { connectState } from "../../redux/connector";
|
||||||
import {
|
import {
|
||||||
getNotificationState,
|
getNotificationState,
|
||||||
|
@ -21,7 +22,6 @@ import { AppContext } from "./RevoltClient";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
options?: NotificationOptions;
|
options?: NotificationOptions;
|
||||||
notifs: Notifications;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const notifications: { [key: string]: Notification } = {};
|
const notifications: { [key: string]: Notification } = {};
|
||||||
|
@ -38,9 +38,10 @@ async function createNotification(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Notifier({ options, notifs }: Props) {
|
function Notifier({ options }: Props) {
|
||||||
const translate = useTranslation();
|
const translate = useTranslation();
|
||||||
const showNotification = options?.desktopEnabled ?? false;
|
const showNotification = options?.desktopEnabled ?? false;
|
||||||
|
const notifs = useApplicationState().notifications;
|
||||||
|
|
||||||
const client = useContext(AppContext);
|
const client = useContext(AppContext);
|
||||||
const { guild: guild_id, channel: channel_id } = useParams<{
|
const { guild: guild_id, channel: channel_id } = useParams<{
|
||||||
|
@ -57,8 +58,7 @@ function Notifier({ options, notifs }: Props) {
|
||||||
if (client.user!.status?.presence === Presence.Busy) return;
|
if (client.user!.status?.presence === Presence.Busy) return;
|
||||||
if (msg.author?.relationship === RelationshipStatus.Blocked) return;
|
if (msg.author?.relationship === RelationshipStatus.Blocked) return;
|
||||||
|
|
||||||
const notifState = getNotificationState(notifs, msg.channel!);
|
if (!notifs.shouldNotify(msg)) return;
|
||||||
if (!shouldNotify(notifState, msg, client.user!._id)) return;
|
|
||||||
|
|
||||||
playSound("message");
|
playSound("message");
|
||||||
if (!showNotification) return;
|
if (!showNotification) return;
|
||||||
|
@ -294,7 +294,6 @@ const NotifierComponent = connectState(
|
||||||
(state) => {
|
(state) => {
|
||||||
return {
|
return {
|
||||||
options: state.settings.notification,
|
options: state.settings.notification,
|
||||||
notifs: state.notifications,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -152,6 +152,6 @@ export default connectState(SyncManager, (state) => {
|
||||||
};
|
};
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
function SyncManager() {
|
export default function SyncManager() {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ import {
|
||||||
StatusContext,
|
StatusContext,
|
||||||
} from "../context/revoltjs/RevoltClient";
|
} from "../context/revoltjs/RevoltClient";
|
||||||
import { takeError } from "../context/revoltjs/util";
|
import { takeError } from "../context/revoltjs/util";
|
||||||
|
import CMNotifications from "./contextmenu/CMNotifications";
|
||||||
|
|
||||||
import Tooltip from "../components/common/Tooltip";
|
import Tooltip from "../components/common/Tooltip";
|
||||||
import UserStatus from "../components/common/user/UserStatus";
|
import UserStatus from "../components/common/user/UserStatus";
|
||||||
|
@ -117,7 +118,11 @@ type Action =
|
||||||
| { action: "leave_server"; target: Server }
|
| { action: "leave_server"; target: Server }
|
||||||
| { action: "delete_server"; target: Server }
|
| { action: "delete_server"; target: Server }
|
||||||
| { action: "edit_identity"; target: Server }
|
| { action: "edit_identity"; target: Server }
|
||||||
| { action: "open_notification_options"; channel: Channel }
|
| {
|
||||||
|
action: "open_notification_options";
|
||||||
|
channel?: Channel;
|
||||||
|
server?: Server;
|
||||||
|
}
|
||||||
| { action: "open_settings" }
|
| { action: "open_settings" }
|
||||||
| { action: "open_channel_settings"; id: string }
|
| { action: "open_channel_settings"; id: string }
|
||||||
| { action: "open_server_settings"; id: string }
|
| { action: "open_server_settings"; id: string }
|
||||||
|
@ -128,13 +133,9 @@ type Action =
|
||||||
state?: NotificationState;
|
state?: NotificationState;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
|
||||||
notifications: Notifications;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ! FIXME: I dare someone to re-write this
|
// ! FIXME: I dare someone to re-write this
|
||||||
// Tip: This should just be split into separate context menus per logical area.
|
// Tip: This should just be split into separate context menus per logical area.
|
||||||
function ContextMenus(props: Props) {
|
export default function ContextMenus() {
|
||||||
const { openScreen, writeClipboard } = useIntermediate();
|
const { openScreen, writeClipboard } = useIntermediate();
|
||||||
const client = useContext(AppContext);
|
const client = useContext(AppContext);
|
||||||
const userId = client.user!._id;
|
const userId = client.user!._id;
|
||||||
|
@ -427,6 +428,7 @@ function ContextMenus(props: Props) {
|
||||||
case "open_notification_options": {
|
case "open_notification_options": {
|
||||||
openContextMenu("NotificationOptions", {
|
openContextMenu("NotificationOptions", {
|
||||||
channel: data.channel,
|
channel: data.channel,
|
||||||
|
server: data.server,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -921,6 +923,16 @@ function ContextMenus(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sid && server) {
|
if (sid && server) {
|
||||||
|
generateAction(
|
||||||
|
{
|
||||||
|
action: "open_notification_options",
|
||||||
|
server,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
<ChevronRight size={24} />,
|
||||||
|
);
|
||||||
|
|
||||||
if (server.channels[0] !== undefined)
|
if (server.channels[0] !== undefined)
|
||||||
generateAction(
|
generateAction(
|
||||||
{
|
{
|
||||||
|
@ -1085,76 +1097,7 @@ function ContextMenus(props: Props) {
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</ContextMenuWithData>
|
</ContextMenuWithData>
|
||||||
<ContextMenuWithData
|
<CMNotifications />
|
||||||
id="NotificationOptions"
|
|
||||||
onClose={contextClick}>
|
|
||||||
{({ channel }: { channel: Channel }) => {
|
|
||||||
const state = props.notifications[channel._id];
|
|
||||||
const actual = getNotificationState(
|
|
||||||
props.notifications,
|
|
||||||
channel,
|
|
||||||
);
|
|
||||||
|
|
||||||
const elements: Children[] = [
|
|
||||||
<MenuItem
|
|
||||||
key="notif"
|
|
||||||
data={{
|
|
||||||
action: "set_notification_state",
|
|
||||||
key: channel._id,
|
|
||||||
}}>
|
|
||||||
<Text
|
|
||||||
id={`app.main.channel.notifications.default`}
|
|
||||||
/>
|
|
||||||
<div className="tip">
|
|
||||||
{state !== undefined && <Square size={20} />}
|
|
||||||
{state === undefined && (
|
|
||||||
<CheckSquare size={20} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</MenuItem>,
|
|
||||||
];
|
|
||||||
|
|
||||||
function generate(key: string, icon: Children) {
|
|
||||||
elements.push(
|
|
||||||
<MenuItem
|
|
||||||
key={key}
|
|
||||||
data={{
|
|
||||||
action: "set_notification_state",
|
|
||||||
key: channel._id,
|
|
||||||
state: key,
|
|
||||||
}}>
|
|
||||||
{icon}
|
|
||||||
<Text
|
|
||||||
id={`app.main.channel.notifications.${key}`}
|
|
||||||
/>
|
|
||||||
{state === undefined && actual === key && (
|
|
||||||
<div className="tip">
|
|
||||||
<LeftArrowAlt size={20} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{state === key && (
|
|
||||||
<div className="tip">
|
|
||||||
<Check size={20} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</MenuItem>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
generate("all", <Bell size={24} />);
|
|
||||||
generate("mention", <At size={24} />);
|
|
||||||
generate("muted", <BellOff size={24} />);
|
|
||||||
generate("none", <Block size={24} />);
|
|
||||||
|
|
||||||
return elements;
|
|
||||||
}}
|
|
||||||
</ContextMenuWithData>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connectState(ContextMenus, (state) => {
|
|
||||||
return {
|
|
||||||
notifications: state.notifications,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
119
src/lib/contextmenu/CMNotifications.tsx
Normal file
119
src/lib/contextmenu/CMNotifications.tsx
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
import {
|
||||||
|
At,
|
||||||
|
Bell,
|
||||||
|
BellOff,
|
||||||
|
Check,
|
||||||
|
CheckSquare,
|
||||||
|
Block,
|
||||||
|
Square,
|
||||||
|
LeftArrowAlt,
|
||||||
|
} from "@styled-icons/boxicons-regular";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
|
|
||||||
|
import { ContextMenuWithData, MenuItem } from "preact-context-menu";
|
||||||
|
import { Text } from "preact-i18n";
|
||||||
|
|
||||||
|
import { useApplicationState } from "../../mobx/State";
|
||||||
|
import { NotificationState } from "../../mobx/stores/NotificationOptions";
|
||||||
|
|
||||||
|
import LineDivider from "../../components/ui/LineDivider";
|
||||||
|
|
||||||
|
import { Children } from "../../types/Preact";
|
||||||
|
|
||||||
|
interface Action {
|
||||||
|
key: string;
|
||||||
|
type: "channel" | "server";
|
||||||
|
state?: NotificationState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a context menu for controlling notification options.
|
||||||
|
*/
|
||||||
|
export default observer(() => {
|
||||||
|
const notifications = useApplicationState().notifications;
|
||||||
|
|
||||||
|
const contextClick = (data?: Action) =>
|
||||||
|
data &&
|
||||||
|
(data.type === "channel"
|
||||||
|
? notifications.setChannelState(data.key, data.state)
|
||||||
|
: notifications.setServerState(data.key, data.state));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ContextMenuWithData id="NotificationOptions" onClose={contextClick}>
|
||||||
|
{({ channel, server }: { channel?: Channel; server?: Server }) => {
|
||||||
|
// Find the computed and actual state values for channel / server.
|
||||||
|
const state = channel
|
||||||
|
? notifications.getChannelState(channel._id)
|
||||||
|
: notifications.computeForServer(server!._id);
|
||||||
|
|
||||||
|
const actual = channel
|
||||||
|
? notifications.computeForChannel(channel)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
// If we're editing channel, show a default option too.
|
||||||
|
const elements: Children[] = channel
|
||||||
|
? [
|
||||||
|
<MenuItem
|
||||||
|
key="notif"
|
||||||
|
data={{
|
||||||
|
key: channel._id,
|
||||||
|
type: "channel",
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
id={`app.main.channel.notifications.default`}
|
||||||
|
/>
|
||||||
|
<div className="tip">
|
||||||
|
{state !== undefined && <Square size={20} />}
|
||||||
|
{state === undefined && (
|
||||||
|
<CheckSquare size={20} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</MenuItem>,
|
||||||
|
<LineDivider />,
|
||||||
|
]
|
||||||
|
: [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new entry we can select.
|
||||||
|
* @param key Notification state
|
||||||
|
* @param icon Icon for this state
|
||||||
|
*/
|
||||||
|
function generate(key: string, icon: Children) {
|
||||||
|
elements.push(
|
||||||
|
<MenuItem
|
||||||
|
key={key}
|
||||||
|
data={{
|
||||||
|
key: channel ? channel._id : server!._id,
|
||||||
|
type: channel ? "channel" : "server",
|
||||||
|
state: key,
|
||||||
|
}}>
|
||||||
|
{icon}
|
||||||
|
<Text
|
||||||
|
id={`app.main.channel.notifications.${key}`}
|
||||||
|
/>
|
||||||
|
{state === undefined && actual === key && (
|
||||||
|
<div className="tip">
|
||||||
|
<LeftArrowAlt size={20} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{state === key && (
|
||||||
|
<div className="tip">
|
||||||
|
<Check size={20} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</MenuItem>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
generate("all", <Bell size={24} />);
|
||||||
|
generate("mention", <At size={24} />);
|
||||||
|
generate("none", <BellOff size={24} />);
|
||||||
|
generate("muted", <Block size={24} />);
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}}
|
||||||
|
</ContextMenuWithData>
|
||||||
|
);
|
||||||
|
});
|
|
@ -10,6 +10,7 @@ import Draft from "./stores/Draft";
|
||||||
import Experiments from "./stores/Experiments";
|
import Experiments from "./stores/Experiments";
|
||||||
import Layout from "./stores/Layout";
|
import Layout from "./stores/Layout";
|
||||||
import LocaleOptions from "./stores/LocaleOptions";
|
import LocaleOptions from "./stores/LocaleOptions";
|
||||||
|
import NotificationOptions from "./stores/NotificationOptions";
|
||||||
import ServerConfig from "./stores/ServerConfig";
|
import ServerConfig from "./stores/ServerConfig";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +23,7 @@ export default class State {
|
||||||
experiments: Experiments;
|
experiments: Experiments;
|
||||||
layout: Layout;
|
layout: Layout;
|
||||||
config: ServerConfig;
|
config: ServerConfig;
|
||||||
|
notifications: NotificationOptions;
|
||||||
|
|
||||||
private persistent: [string, Persistent<unknown>][] = [];
|
private persistent: [string, Persistent<unknown>][] = [];
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ export default class State {
|
||||||
this.experiments = new Experiments();
|
this.experiments = new Experiments();
|
||||||
this.layout = new Layout();
|
this.layout = new Layout();
|
||||||
this.config = new ServerConfig();
|
this.config = new ServerConfig();
|
||||||
|
this.notifications = new NotificationOptions();
|
||||||
|
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
this.registerListeners = this.registerListeners.bind(this);
|
this.registerListeners = this.registerListeners.bind(this);
|
||||||
|
|
|
@ -49,9 +49,7 @@ export function findLanguage(lang?: string): Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of the last open channels, tabs, etc.
|
* Keeps track of user's language settings.
|
||||||
* Handles providing good UX experience on navigating
|
|
||||||
* back and forth between different parts of the app.
|
|
||||||
*/
|
*/
|
||||||
export default class LocaleOptions implements Store, Persistent<Data> {
|
export default class LocaleOptions implements Store, Persistent<Data> {
|
||||||
private lang: Language;
|
private lang: Language;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { action, computed, makeAutoObservable, ObservableMap } from "mobx";
|
import { action, computed, makeAutoObservable, ObservableMap } from "mobx";
|
||||||
import { Channel } from "revolt-api/types/Channels";
|
import { Channel } from "revolt.js/dist/maps/Channels";
|
||||||
|
import { Message } from "revolt.js/dist/maps/Messages";
|
||||||
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
|
|
||||||
import { mapToRecord } from "../../lib/conversion";
|
import { mapToRecord } from "../../lib/conversion";
|
||||||
|
|
||||||
|
@ -22,21 +24,26 @@ export const DEFAULT_STATES: {
|
||||||
SavedMessages: "all",
|
SavedMessages: "all",
|
||||||
DirectMessage: "all",
|
DirectMessage: "all",
|
||||||
Group: "all",
|
Group: "all",
|
||||||
TextChannel: "mention",
|
TextChannel: undefined!,
|
||||||
VoiceChannel: "mention",
|
VoiceChannel: undefined!,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default state for servers.
|
||||||
|
*/
|
||||||
|
export const DEFAULT_SERVER_STATE: NotificationState = "mention";
|
||||||
|
|
||||||
interface Data {
|
interface Data {
|
||||||
server?: Record<string, string>;
|
server?: Record<string, NotificationState>;
|
||||||
channel?: Record<string, string>;
|
channel?: Record<string, NotificationState>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the user's notification preferences.
|
* Manages the user's notification preferences.
|
||||||
*/
|
*/
|
||||||
export default class NotificationOptions implements Store, Persistent<Data> {
|
export default class NotificationOptions implements Store, Persistent<Data> {
|
||||||
private server: ObservableMap<string, string>;
|
private server: ObservableMap<string, NotificationState>;
|
||||||
private channel: ObservableMap<string, string>;
|
private channel: ObservableMap<string, NotificationState>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct new Experiments store.
|
* Construct new Experiments store.
|
||||||
|
@ -72,5 +79,72 @@ export default class NotificationOptions implements Store, Persistent<Data> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement
|
computeForChannel(channel: Channel) {
|
||||||
|
if (this.channel.has(channel._id)) {
|
||||||
|
return this.channel.get(channel._id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel.server_id) {
|
||||||
|
return this.computeForServer(channel.server_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_STATES[channel.channel_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldNotify(message: Message) {
|
||||||
|
const state = this.computeForChannel(message.channel!);
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case "muted":
|
||||||
|
case "none":
|
||||||
|
return false;
|
||||||
|
case "mention":
|
||||||
|
if (!message.mention_ids?.includes(message.client.user!._id))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeForServer(server_id: string) {
|
||||||
|
if (this.server.has(server_id)) {
|
||||||
|
return this.server.get(server_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_SERVER_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
getChannelState(channel_id: string) {
|
||||||
|
return this.channel.get(channel_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
setChannelState(channel_id: string, state?: NotificationState) {
|
||||||
|
if (state) {
|
||||||
|
this.channel.set(channel_id, state);
|
||||||
|
} else {
|
||||||
|
this.channel.delete(channel_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getServerState(server_id: string) {
|
||||||
|
return this.server.get(server_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
setServerState(server_id: string, state?: NotificationState) {
|
||||||
|
if (state) {
|
||||||
|
this.server.set(server_id, state);
|
||||||
|
} else {
|
||||||
|
this.server.delete(server_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isMuted(target?: Channel | Server) {
|
||||||
|
if (target instanceof Channel) {
|
||||||
|
return this.computeForChannel(target) === "muted";
|
||||||
|
} else if (target instanceof Server) {
|
||||||
|
return this.computeForServer(target._id) === "muted";
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue