mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-24 22:52:09 -05:00
Feature: Basic notification options implementation
This commit is contained in:
parent
51ac1f599c
commit
21859e4c55
10 changed files with 173 additions and 25 deletions
2
external/lang
vendored
2
external/lang
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 099fb74131c60955e8226ce0a290cb22e959d7d6
|
Subproject commit 9cc46c3a4abab74e17e56597db10e2c16ac0f9b5
|
|
@ -116,7 +116,7 @@ export default function Intermediate(props: Props) {
|
||||||
screen.id
|
screen.id
|
||||||
} /** By specifying a key, we reset state whenever switching screen. */
|
} /** By specifying a key, we reset state whenever switching screen. */
|
||||||
/>
|
/>
|
||||||
{/*<Prompt
|
<Prompt
|
||||||
when={[ 'modify_account', 'special_prompt', 'special_input', 'image_viewer', 'profile', 'channel_info', 'user_picker' ].includes(screen.id)}
|
when={[ 'modify_account', 'special_prompt', 'special_input', 'image_viewer', 'profile', 'channel_info', 'user_picker' ].includes(screen.id)}
|
||||||
message={(_, action) => {
|
message={(_, action) => {
|
||||||
if (action === 'POP') {
|
if (action === 'POP') {
|
||||||
|
@ -128,7 +128,7 @@ export default function Intermediate(props: Props) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}}
|
}}
|
||||||
/>*/}
|
/>
|
||||||
</IntermediateActionsContext.Provider>
|
</IntermediateActionsContext.Provider>
|
||||||
</IntermediateContext.Provider>
|
</IntermediateContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,9 +8,11 @@ import { connectState } from "../../redux/connector";
|
||||||
import { Message, SYSTEM_USER_ID, User } from "revolt.js";
|
import { Message, SYSTEM_USER_ID, User } from "revolt.js";
|
||||||
import { NotificationOptions } from "../../redux/reducers/settings";
|
import { NotificationOptions } from "../../redux/reducers/settings";
|
||||||
import { Route, Switch, useHistory, useParams } from "react-router-dom";
|
import { Route, Switch, useHistory, useParams } from "react-router-dom";
|
||||||
|
import { getNotificationState, Notifications } from "../../redux/reducers/notifications";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
options?: NotificationOptions;
|
options?: NotificationOptions;
|
||||||
|
notifs: Notifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
const notifications: { [key: string]: Notification } = {};
|
const notifications: { [key: string]: Notification } = {};
|
||||||
|
@ -24,9 +26,9 @@ async function createNotification(title: string, options: globalThis.Notificatio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Notifier(props: Props) {
|
function Notifier({ options, notifs }: Props) {
|
||||||
const translate = useTranslation();
|
const translate = useTranslation();
|
||||||
const showNotification = props.options?.desktopEnabled ?? false;
|
const showNotification = options?.desktopEnabled ?? false;
|
||||||
|
|
||||||
const client = useContext(AppContext);
|
const client = useContext(AppContext);
|
||||||
const { guild: guild_id, channel: channel_id } = useParams<{
|
const { guild: guild_id, channel: channel_id } = useParams<{
|
||||||
|
@ -39,17 +41,27 @@ function Notifier(props: Props) {
|
||||||
async function message(msg: Message) {
|
async function message(msg: Message) {
|
||||||
if (msg.author === client.user!._id) return;
|
if (msg.author === client.user!._id) return;
|
||||||
if (msg.channel === channel_id && document.hasFocus()) return;
|
if (msg.channel === channel_id && document.hasFocus()) return;
|
||||||
if (client.user?.status?.presence === Users.Presence.Busy) return;
|
if (client.user!.status?.presence === Users.Presence.Busy) return;
|
||||||
|
|
||||||
|
const channel = client.channels.get(msg.channel);
|
||||||
|
const author = client.users.get(msg.author);
|
||||||
|
if (!channel) return;
|
||||||
|
if (author?.relationship === Users.Relationship.Blocked) return;
|
||||||
|
|
||||||
|
const notifState = getNotificationState(notifs, channel);
|
||||||
|
switch (notifState) {
|
||||||
|
case 'muted':
|
||||||
|
case 'none': return;
|
||||||
|
case 'mention': {
|
||||||
|
if (!msg.mentions?.includes(client.user!._id)) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
playSound('message');
|
playSound('message');
|
||||||
if (!showNotification) return;
|
if (!showNotification) return;
|
||||||
|
|
||||||
const channel = client.channels.get(msg.channel);
|
|
||||||
const author = client.users.get(msg.author);
|
|
||||||
if (author?.relationship === Users.Relationship.Blocked) return;
|
|
||||||
|
|
||||||
let title;
|
let title;
|
||||||
switch (channel?.channel_type) {
|
switch (channel.channel_type) {
|
||||||
case "SavedMessages":
|
case "SavedMessages":
|
||||||
return;
|
return;
|
||||||
case "DirectMessage":
|
case "DirectMessage":
|
||||||
|
@ -192,7 +204,7 @@ function Notifier(props: Props) {
|
||||||
client.removeListener("message", message);
|
client.removeListener("message", message);
|
||||||
client.users.removeListener("mutation", relationship);
|
client.users.removeListener("mutation", relationship);
|
||||||
};
|
};
|
||||||
}, [client, playSound, guild_id, channel_id, showNotification]);
|
}, [client, playSound, guild_id, channel_id, showNotification, notifs]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function visChange() {
|
function visChange() {
|
||||||
|
@ -217,7 +229,8 @@ const NotifierComponent = connectState(
|
||||||
Notifier,
|
Notifier,
|
||||||
state => {
|
state => {
|
||||||
return {
|
return {
|
||||||
options: state.settings.notification
|
options: state.settings.notification,
|
||||||
|
notifs: state.notifications
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { useContext, useEffect } from "preact/hooks";
|
||||||
import { connectState } from "../../redux/connector";
|
import { connectState } from "../../redux/connector";
|
||||||
import { WithDispatcher } from "../../redux/reducers";
|
import { WithDispatcher } from "../../redux/reducers";
|
||||||
import { Settings } from "../../redux/reducers/settings";
|
import { Settings } from "../../redux/reducers/settings";
|
||||||
|
import { Notifications } from "../../redux/reducers/notifications";
|
||||||
import { AppContext, ClientStatus, StatusContext } from "./RevoltClient";
|
import { AppContext, ClientStatus, StatusContext } from "./RevoltClient";
|
||||||
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
||||||
import { DEFAULT_ENABLED_SYNC, SyncData, SyncKeys, SyncOptions } from "../../redux/reducers/sync";
|
import { DEFAULT_ENABLED_SYNC, SyncData, SyncKeys, SyncOptions } from "../../redux/reducers/sync";
|
||||||
|
@ -16,7 +17,8 @@ import { DEFAULT_ENABLED_SYNC, SyncData, SyncKeys, SyncOptions } from "../../red
|
||||||
type Props = WithDispatcher & {
|
type Props = WithDispatcher & {
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
locale: Language,
|
locale: Language,
|
||||||
sync: SyncOptions
|
sync: SyncOptions,
|
||||||
|
notifications: Notifications
|
||||||
};
|
};
|
||||||
|
|
||||||
var lastValues: { [key in SyncKeys]?: any } = { };
|
var lastValues: { [key in SyncKeys]?: any } = { };
|
||||||
|
@ -78,7 +80,7 @@ function SyncManager(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let disabled = props.sync.disabled ?? [];
|
let disabled = props.sync.disabled ?? [];
|
||||||
for (let [key, object] of [ ['appearance', props.settings.appearance], ['theme', props.settings.theme], ['locale', props.locale] ] as [SyncKeys, any][]) {
|
for (let [key, object] of [ ['appearance', props.settings.appearance], ['theme', props.settings.theme], ['locale', props.locale], ['notifications', props.notifications] ] as [SyncKeys, any][]) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (disabled.indexOf(key) === -1) {
|
if (disabled.indexOf(key) === -1) {
|
||||||
if (typeof lastValues[key] !== 'undefined') {
|
if (typeof lastValues[key] !== 'undefined') {
|
||||||
|
@ -117,7 +119,8 @@ export default connectState(
|
||||||
return {
|
return {
|
||||||
settings: state.settings,
|
settings: state.settings,
|
||||||
locale: state.locale,
|
locale: state.locale,
|
||||||
sync: state.sync
|
sync: state.sync,
|
||||||
|
notifications: state.notifications
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { Attachment, Channels, Message, Servers, Users } from "revolt.js/dist/ap
|
||||||
import {
|
import {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
ContextMenuWithData,
|
ContextMenuWithData,
|
||||||
MenuItem
|
MenuItem,
|
||||||
|
openContextMenu
|
||||||
} from "preact-context-menu";
|
} from "preact-context-menu";
|
||||||
import { ChannelPermission, ServerPermission, UserPermission } from "revolt.js/dist/api/permissions";
|
import { ChannelPermission, ServerPermission, UserPermission } from "revolt.js/dist/api/permissions";
|
||||||
import { QueuedMessage } from "../redux/reducers/queue";
|
import { QueuedMessage } from "../redux/reducers/queue";
|
||||||
|
@ -18,6 +19,9 @@ import { Children } from "../types/Preact";
|
||||||
import LineDivider from "../components/ui/LineDivider";
|
import LineDivider from "../components/ui/LineDivider";
|
||||||
import { connectState } from "../redux/connector";
|
import { connectState } from "../redux/connector";
|
||||||
import { internalEmit } from "./eventEmitter";
|
import { internalEmit } from "./eventEmitter";
|
||||||
|
import { AtSign, Bell, BellOff, Check, CheckSquare, ChevronRight, Slash, Square } from "@styled-icons/feather";
|
||||||
|
import { getNotificationState, Notifications, NotificationState } from "../redux/reducers/notifications";
|
||||||
|
import { ArrowLeft } from "@styled-icons/bootstrap";
|
||||||
|
|
||||||
interface ContextMenuData {
|
interface ContextMenuData {
|
||||||
user?: string;
|
user?: string;
|
||||||
|
@ -68,11 +72,17 @@ type Action =
|
||||||
| { action: "close_dm"; target: Channels.DirectMessageChannel }
|
| { action: "close_dm"; target: Channels.DirectMessageChannel }
|
||||||
| { action: "leave_server"; target: Servers.Server }
|
| { action: "leave_server"; target: Servers.Server }
|
||||||
| { action: "delete_server"; target: Servers.Server }
|
| { action: "delete_server"; target: Servers.Server }
|
||||||
|
| { action: "open_notification_options", channel: Channels.Channel }
|
||||||
| { action: "open_channel_settings", id: string }
|
| { action: "open_channel_settings", id: string }
|
||||||
| { action: "open_server_settings", id: string }
|
| { action: "open_server_settings", id: string }
|
||||||
| { action: "open_server_channel_settings", server: string, id: string };
|
| { action: "open_server_channel_settings", server: string, id: string }
|
||||||
|
| { action: "set_notification_state", key: string, state?: NotificationState };
|
||||||
|
|
||||||
function ContextMenus(props: WithDispatcher) {
|
type Props = WithDispatcher & {
|
||||||
|
notifications: Notifications
|
||||||
|
};
|
||||||
|
|
||||||
|
function ContextMenus(props: Props) {
|
||||||
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;
|
||||||
|
@ -301,9 +311,24 @@ function ContextMenus(props: WithDispatcher) {
|
||||||
case "ban_member":
|
case "ban_member":
|
||||||
case "kick_member": openScreen({ id: "special_prompt", type: data.action, target: data.target, user: data.user }); break;
|
case "kick_member": openScreen({ id: "special_prompt", type: data.action, target: data.target, user: data.user }); break;
|
||||||
|
|
||||||
|
case "open_notification_options": {
|
||||||
|
openContextMenu("NotificationOptions", { channel: data.channel });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "open_channel_settings": history.push(`/channel/${data.id}/settings`); break;
|
case "open_channel_settings": history.push(`/channel/${data.id}/settings`); break;
|
||||||
case "open_server_channel_settings": history.push(`/server/${data.server}/channel/${data.id}/settings`); break;
|
case "open_server_channel_settings": history.push(`/server/${data.server}/channel/${data.id}/settings`); break;
|
||||||
case "open_server_settings": history.push(`/server/${data.id}/settings`); break;
|
case "open_server_settings": history.push(`/server/${data.id}/settings`); break;
|
||||||
|
|
||||||
|
case "set_notification_state": {
|
||||||
|
const { key, state } = data;
|
||||||
|
if (state) {
|
||||||
|
props.dispatcher({ type: "NOTIFICATIONS_SET", key, state });
|
||||||
|
} else {
|
||||||
|
props.dispatcher({ type: "NOTIFICATIONS_REMOVE", key });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})().catch(err => {
|
})().catch(err => {
|
||||||
openScreen({ id: "error", error: takeError(err) });
|
openScreen({ id: "error", error: takeError(err) });
|
||||||
|
@ -567,6 +592,10 @@ function ContextMenus(props: WithDispatcher) {
|
||||||
pushDivider();
|
pushDivider();
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
|
if (channel.channel_type !== 'VoiceChannel') {
|
||||||
|
generateAction({ action: "open_notification_options", channel }, undefined, undefined, <ChevronRight size={24} />);
|
||||||
|
}
|
||||||
|
|
||||||
switch (channel.channel_type) {
|
switch (channel.channel_type) {
|
||||||
case 'Group':
|
case 'Group':
|
||||||
// ! generateAction({ action: "create_invite", target: channel }); FIXME: add support for group invites
|
// ! generateAction({ action: "create_invite", target: channel }); FIXME: add support for group invites
|
||||||
|
@ -669,14 +698,50 @@ function ContextMenus(props: WithDispatcher) {
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
|
<ContextMenuWithData id="NotificationOptions" onClose={contextClick}>
|
||||||
|
{({ channel }: { channel: Channels.Channel }) => {
|
||||||
|
const state = props.notifications[channel._id];
|
||||||
|
const actual = getNotificationState(props.notifications, channel);
|
||||||
|
|
||||||
|
let elements: Children[] = [
|
||||||
|
<MenuItem 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 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"><ArrowLeft size={20} /></div> }
|
||||||
|
{ (state === key) && <div className="tip"><Check size={20} /></div> }
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
generate('all', <Bell size={24} />);
|
||||||
|
generate('mention', <AtSign size={24} />);
|
||||||
|
generate('muted', <BellOff size={24} />);
|
||||||
|
generate('none', <Slash size={24} />);
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}}
|
||||||
|
</ContextMenuWithData>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connectState(
|
export default connectState(
|
||||||
ContextMenus,
|
ContextMenus,
|
||||||
() => {
|
state => {
|
||||||
return {};
|
return {
|
||||||
|
notifications: state.notifications
|
||||||
|
};
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,6 +20,7 @@ export function Component(props: Props & WithDispatcher) {
|
||||||
['appearance', 'appearance.title'],
|
['appearance', 'appearance.title'],
|
||||||
['theme', 'appearance.theme'],
|
['theme', 'appearance.theme'],
|
||||||
['locale', 'language.title']
|
['locale', 'language.title']
|
||||||
|
// notifications sync is always-on
|
||||||
] as [ SyncKeys, string ][]).map(
|
] as [ SyncKeys, string ][]).map(
|
||||||
([ key, title ]) =>
|
([ key, title ]) =>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { Settings } from "./reducers/settings";
|
||||||
import { QueuedMessage } from "./reducers/queue";
|
import { QueuedMessage } from "./reducers/queue";
|
||||||
import { ExperimentOptions } from "./reducers/experiments";
|
import { ExperimentOptions } from "./reducers/experiments";
|
||||||
import { LastOpened } from "./reducers/last_opened";
|
import { LastOpened } from "./reducers/last_opened";
|
||||||
|
import { Notifications } from "./reducers/notifications";
|
||||||
|
|
||||||
export type State = {
|
export type State = {
|
||||||
config: Core.RevoltNodeConfiguration,
|
config: Core.RevoltNodeConfiguration,
|
||||||
|
@ -26,6 +27,7 @@ export type State = {
|
||||||
sync: SyncOptions;
|
sync: SyncOptions;
|
||||||
experiments: ExperimentOptions;
|
experiments: ExperimentOptions;
|
||||||
lastOpened: LastOpened;
|
lastOpened: LastOpened;
|
||||||
|
notifications: Notifications;
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
@ -53,7 +55,8 @@ store.subscribe(() => {
|
||||||
drafts,
|
drafts,
|
||||||
sync,
|
sync,
|
||||||
experiments,
|
experiments,
|
||||||
lastOpened
|
lastOpened,
|
||||||
|
notifications
|
||||||
} = store.getState() as State;
|
} = store.getState() as State;
|
||||||
|
|
||||||
localForage.setItem("state", {
|
localForage.setItem("state", {
|
||||||
|
@ -66,6 +69,7 @@ store.subscribe(() => {
|
||||||
drafts,
|
drafts,
|
||||||
sync,
|
sync,
|
||||||
experiments,
|
experiments,
|
||||||
lastOpened
|
lastOpened,
|
||||||
|
notifications
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { drafts, DraftAction } from "./drafts";
|
||||||
import { sync, SyncAction } from "./sync";
|
import { sync, SyncAction } from "./sync";
|
||||||
import { experiments, ExperimentsAction } from "./experiments";
|
import { experiments, ExperimentsAction } from "./experiments";
|
||||||
import { lastOpened, LastOpenedAction } from "./last_opened";
|
import { lastOpened, LastOpenedAction } from "./last_opened";
|
||||||
|
import { notifications, NotificationsAction } from "./notifications";
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
config,
|
config,
|
||||||
|
@ -24,7 +25,8 @@ export default combineReducers({
|
||||||
drafts,
|
drafts,
|
||||||
sync,
|
sync,
|
||||||
experiments,
|
experiments,
|
||||||
lastOpened
|
lastOpened,
|
||||||
|
notifications
|
||||||
});
|
});
|
||||||
|
|
||||||
export type Action =
|
export type Action =
|
||||||
|
@ -39,6 +41,7 @@ export type Action =
|
||||||
| SyncAction
|
| SyncAction
|
||||||
| ExperimentsAction
|
| ExperimentsAction
|
||||||
| LastOpenedAction
|
| LastOpenedAction
|
||||||
|
| NotificationsAction
|
||||||
| { type: "__INIT"; state: State };
|
| { type: "__INIT"; state: State };
|
||||||
|
|
||||||
export type WithDispatcher = { dispatcher: (action: Action) => void };
|
export type WithDispatcher = { dispatcher: (action: Action) => void };
|
||||||
|
|
56
src/redux/reducers/notifications.ts
Normal file
56
src/redux/reducers/notifications.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { Channel } from "revolt.js";
|
||||||
|
|
||||||
|
export type NotificationState = 'all' | 'mention' | 'none' | 'muted';
|
||||||
|
|
||||||
|
export type Notifications = {
|
||||||
|
[key: string]: NotificationState
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_STATES: { [key in Channel['channel_type']]: NotificationState } = {
|
||||||
|
'SavedMessages': 'all',
|
||||||
|
'DirectMessage': 'all',
|
||||||
|
'Group': 'all',
|
||||||
|
'TextChannel': 'mention',
|
||||||
|
'VoiceChannel': 'mention'
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getNotificationState(notifications: Notifications, channel: Channel) {
|
||||||
|
return notifications[channel._id] ?? DEFAULT_STATES[channel.channel_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NotificationsAction =
|
||||||
|
| { type: undefined }
|
||||||
|
| {
|
||||||
|
type: "NOTIFICATIONS_SET";
|
||||||
|
key: string;
|
||||||
|
state: NotificationState;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "NOTIFICATIONS_REMOVE";
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "RESET";
|
||||||
|
};
|
||||||
|
|
||||||
|
export function notifications(
|
||||||
|
state = {} as Notifications,
|
||||||
|
action: NotificationsAction
|
||||||
|
): Notifications {
|
||||||
|
switch (action.type) {
|
||||||
|
case "NOTIFICATIONS_SET":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
[action.key]: action.state
|
||||||
|
};
|
||||||
|
case "NOTIFICATIONS_REMOVE":
|
||||||
|
{
|
||||||
|
const { [action.key]: _, ...newState } = state;
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
case "RESET":
|
||||||
|
return {};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,22 @@
|
||||||
import { AppearanceOptions } from "./settings";
|
import { AppearanceOptions } from "./settings";
|
||||||
import { Language } from "../../context/Locale";
|
import { Language } from "../../context/Locale";
|
||||||
import { ThemeOptions } from "../../context/Theme";
|
import { ThemeOptions } from "../../context/Theme";
|
||||||
|
import { Notifications } from "./notifications";
|
||||||
|
|
||||||
export type SyncKeys = "theme" | "appearance" | "locale";
|
export type SyncKeys = "theme" | "appearance" | "locale" | "notifications";
|
||||||
|
|
||||||
export interface SyncData {
|
export interface SyncData {
|
||||||
locale?: Language;
|
locale?: Language;
|
||||||
theme?: ThemeOptions;
|
theme?: ThemeOptions;
|
||||||
appearance?: AppearanceOptions;
|
appearance?: AppearanceOptions;
|
||||||
|
notifications?: Notifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_ENABLED_SYNC: SyncKeys[] = [
|
export const DEFAULT_ENABLED_SYNC: SyncKeys[] = [
|
||||||
"theme",
|
"theme",
|
||||||
"appearance",
|
"appearance",
|
||||||
"locale",
|
"locale",
|
||||||
|
"notifications"
|
||||||
];
|
];
|
||||||
export interface SyncOptions {
|
export interface SyncOptions {
|
||||||
disabled?: SyncKeys[];
|
disabled?: SyncKeys[];
|
||||||
|
|
Loading…
Reference in a new issue