mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-24 06:32:08 -05:00
Notifications: Block muted channels from push notifs.
This commit is contained in:
parent
21859e4c55
commit
994ef65200
10 changed files with 53 additions and 29 deletions
|
@ -8,7 +8,7 @@ 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";
|
import { getNotificationState, Notifications, shouldNotify } from "../../redux/reducers/notifications";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
options?: NotificationOptions;
|
options?: NotificationOptions;
|
||||||
|
@ -49,13 +49,7 @@ function Notifier({ options, notifs }: Props) {
|
||||||
if (author?.relationship === Users.Relationship.Blocked) return;
|
if (author?.relationship === Users.Relationship.Blocked) return;
|
||||||
|
|
||||||
const notifState = getNotificationState(notifs, channel);
|
const notifState = getNotificationState(notifs, channel);
|
||||||
switch (notifState) {
|
if (!shouldNotify(notifState, msg, client.user!._id)) return;
|
||||||
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;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Auth } from "revolt.js/dist/api/objects";
|
import type { Auth } from "revolt.js/dist/api/objects";
|
||||||
|
|
||||||
export interface AuthState {
|
export interface AuthState {
|
||||||
accounts: {
|
accounts: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Language } from "../../context/Locale";
|
import { Language } from "../../context/Locale";
|
||||||
import { SyncUpdateAction } from "./sync";
|
import type { SyncUpdateAction } from "./sync";
|
||||||
|
|
||||||
export type LocaleAction =
|
export type LocaleAction =
|
||||||
| { type: undefined }
|
| { type: undefined }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Channel } from "revolt.js";
|
import type { Channel, Message } from "revolt.js";
|
||||||
|
import type { SyncUpdateAction } from "./sync";
|
||||||
|
|
||||||
export type NotificationState = 'all' | 'mention' | 'none' | 'muted';
|
export type NotificationState = 'all' | 'mention' | 'none' | 'muted';
|
||||||
|
|
||||||
|
@ -18,6 +19,18 @@ export function getNotificationState(notifications: Notifications, channel: Chan
|
||||||
return notifications[channel._id] ?? DEFAULT_STATES[channel.channel_type];
|
return notifications[channel._id] ?? DEFAULT_STATES[channel.channel_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shouldNotify(state: NotificationState, message: Message, user_id: string) {
|
||||||
|
switch (state) {
|
||||||
|
case 'muted':
|
||||||
|
case 'none': return false;
|
||||||
|
case 'mention': {
|
||||||
|
if (!message.mentions?.includes(user_id)) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export type NotificationsAction =
|
export type NotificationsAction =
|
||||||
| { type: undefined }
|
| { type: undefined }
|
||||||
| {
|
| {
|
||||||
|
@ -29,6 +42,7 @@ export type NotificationsAction =
|
||||||
type: "NOTIFICATIONS_REMOVE";
|
type: "NOTIFICATIONS_REMOVE";
|
||||||
key: string;
|
key: string;
|
||||||
}
|
}
|
||||||
|
| SyncUpdateAction
|
||||||
| {
|
| {
|
||||||
type: "RESET";
|
type: "RESET";
|
||||||
};
|
};
|
||||||
|
@ -48,6 +62,8 @@ export function notifications(
|
||||||
const { [action.key]: _, ...newState } = state;
|
const { [action.key]: _, ...newState } = state;
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
case "SYNC_UPDATE":
|
||||||
|
return action.update.notifications?.[1] ?? state;
|
||||||
case "RESET":
|
case "RESET":
|
||||||
return {};
|
return {};
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { MessageObject } from "../../context/revoltjs/util";
|
import type { MessageObject } from "../../context/revoltjs/util";
|
||||||
|
|
||||||
export enum QueueStatus {
|
export enum QueueStatus {
|
||||||
SENDING = "sending",
|
SENDING = "sending",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Core } from "revolt.js/dist/api/objects";
|
import type { Core } from "revolt.js/dist/api/objects";
|
||||||
|
|
||||||
export type ConfigAction =
|
export type ConfigAction =
|
||||||
| { type: undefined }
|
| { type: undefined }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { filter } from ".";
|
import { filter } from ".";
|
||||||
import { SyncUpdateAction } from "./sync";
|
import type { SyncUpdateAction } from "./sync";
|
||||||
import { Sounds } from "../../assets/sounds/Audio";
|
import type { Sounds } from "../../assets/sounds/Audio";
|
||||||
import { Theme, ThemeOptions } from "../../context/Theme";
|
import type { Theme, ThemeOptions } from "../../context/Theme";
|
||||||
import { setEmojiPack } from "../../components/common/Emoji";
|
import { setEmojiPack } from "../../components/common/Emoji";
|
||||||
|
|
||||||
export type SoundOptions = {
|
export type SoundOptions = {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { AppearanceOptions } from "./settings";
|
import type { AppearanceOptions } from "./settings";
|
||||||
import { Language } from "../../context/Locale";
|
import type { Language } from "../../context/Locale";
|
||||||
import { ThemeOptions } from "../../context/Theme";
|
import type { ThemeOptions } from "../../context/Theme";
|
||||||
import { Notifications } from "./notifications";
|
import type { Notifications } from "./notifications";
|
||||||
|
|
||||||
export type SyncKeys = "theme" | "appearance" | "locale" | "notifications";
|
export type SyncKeys = "theme" | "appearance" | "locale" | "notifications";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Sync } from "revolt.js/dist/api/objects";
|
import type { Sync } from "revolt.js/dist/api/objects";
|
||||||
|
|
||||||
export interface Unreads {
|
export interface Unreads {
|
||||||
[key: string]: Partial<Omit<Sync.ChannelUnread, "_id">>;
|
[key: string]: Partial<Omit<Sync.ChannelUnread, "_id">>;
|
||||||
|
|
30
src/sw.ts
30
src/sw.ts
|
@ -3,6 +3,9 @@ import { precacheAndRoute } from 'workbox-precaching'
|
||||||
import { Server } from 'revolt.js/dist/api/objects'
|
import { Server } from 'revolt.js/dist/api/objects'
|
||||||
import { Channel, Message, User } from 'revolt.js'
|
import { Channel, Message, User } from 'revolt.js'
|
||||||
import { IDBPDatabase, openDB } from 'idb'
|
import { IDBPDatabase, openDB } from 'idb'
|
||||||
|
import { getItem } from 'localforage'
|
||||||
|
import type { State } from './redux'
|
||||||
|
import { getNotificationState, shouldNotify } from './redux/reducers/notifications'
|
||||||
|
|
||||||
declare let self: ServiceWorkerGlobalScope
|
declare let self: ServiceWorkerGlobalScope
|
||||||
|
|
||||||
|
@ -34,12 +37,18 @@ function decodeTime(id: string) {
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
const base_url = `https://autumn.revolt.chat`;
|
|
||||||
self.addEventListener("push", event => {
|
self.addEventListener("push", event => {
|
||||||
async function process() {
|
async function process() {
|
||||||
if (event.data === null) return;
|
if (event.data === null) return;
|
||||||
let data: Message = event.data.json();
|
let data: Message = event.data.json();
|
||||||
|
|
||||||
|
let item = await localStorage.getItem('state');
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
|
const state: State = JSON.parse(item);
|
||||||
|
const autumn_url = state.config.features.autumn.url;
|
||||||
|
const user_id = state.auth.active!;
|
||||||
|
|
||||||
let db: IDBPDatabase;
|
let db: IDBPDatabase;
|
||||||
try {
|
try {
|
||||||
// Match RevoltClient.tsx#L55
|
// Match RevoltClient.tsx#L55
|
||||||
|
@ -65,19 +74,24 @@ self.addEventListener("push", event => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let channel = await get<Channel>('channels', data.channel);
|
||||||
|
let user = await get<User>('users', data.author);
|
||||||
|
|
||||||
|
if (channel) {
|
||||||
|
const notifs = getNotificationState(state.notifications, channel);
|
||||||
|
if (!shouldNotify(notifs, data, user_id)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let title = `@${data.author}`;
|
||||||
|
let username = user?.username ?? data.author;
|
||||||
let image;
|
let image;
|
||||||
if (data.attachments) {
|
if (data.attachments) {
|
||||||
let attachment = data.attachments[0];
|
let attachment = data.attachments[0];
|
||||||
if (attachment.metadata.type === "Image") {
|
if (attachment.metadata.type === "Image") {
|
||||||
image = `${base_url}/${attachment.tag}/${attachment._id}`;
|
image = `${autumn_url}/${attachment.tag}/${attachment._id}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = `@${data.author}`;
|
|
||||||
let channel = await get<Channel>('channels', data.channel);
|
|
||||||
let user = await get<User>('users', data.author);
|
|
||||||
let username = user?.username ?? data.author;
|
|
||||||
|
|
||||||
switch (channel?.channel_type) {
|
switch (channel?.channel_type) {
|
||||||
case "SavedMessages": break;
|
case "SavedMessages": break;
|
||||||
case "DirectMessage": title = `@${username}`; break;
|
case "DirectMessage": title = `@${username}`; break;
|
||||||
|
@ -97,7 +111,7 @@ self.addEventListener("push", event => {
|
||||||
}
|
}
|
||||||
|
|
||||||
await self.registration.showNotification(title, {
|
await self.registration.showNotification(title, {
|
||||||
icon: user?.avatar ? `${base_url}/${user.avatar.tag}/${user.avatar._id}` : `https://api.revolt.chat/users/${data.author}/default_avatar`,
|
icon: user?.avatar ? `${autumn_url}/${user.avatar.tag}/${user.avatar._id}` : `https://api.revolt.chat/users/${data.author}/default_avatar`,
|
||||||
image,
|
image,
|
||||||
body: typeof data.content === "string" ? data.content : JSON.stringify(data.content),
|
body: typeof data.content === "string" ? data.content : JSON.stringify(data.content),
|
||||||
timestamp: decodeTime(data._id),
|
timestamp: decodeTime(data._id),
|
||||||
|
|
Loading…
Reference in a new issue