Notifications: Block muted channels from push notifs.

This commit is contained in:
Paul 2021-06-25 12:37:59 +01:00
parent 21859e4c55
commit 994ef65200
10 changed files with 53 additions and 29 deletions

View file

@ -8,7 +8,7 @@ import { connectState } from "../../redux/connector";
import { Message, SYSTEM_USER_ID, User } from "revolt.js";
import { NotificationOptions } from "../../redux/reducers/settings";
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 {
options?: NotificationOptions;
@ -49,13 +49,7 @@ function Notifier({ options, notifs }: Props) {
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;
}
}
if (!shouldNotify(notifState, msg, client.user!._id)) return;
playSound('message');
if (!showNotification) return;

View file

@ -1,4 +1,4 @@
import { Auth } from "revolt.js/dist/api/objects";
import type { Auth } from "revolt.js/dist/api/objects";
export interface AuthState {
accounts: {

View file

@ -1,5 +1,5 @@
import { Language } from "../../context/Locale";
import { SyncUpdateAction } from "./sync";
import type { SyncUpdateAction } from "./sync";
export type LocaleAction =
| { type: undefined }

View file

@ -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';
@ -18,6 +19,18 @@ export function getNotificationState(notifications: Notifications, channel: Chan
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 =
| { type: undefined }
| {
@ -29,6 +42,7 @@ export type NotificationsAction =
type: "NOTIFICATIONS_REMOVE";
key: string;
}
| SyncUpdateAction
| {
type: "RESET";
};
@ -48,6 +62,8 @@ export function notifications(
const { [action.key]: _, ...newState } = state;
return newState;
}
case "SYNC_UPDATE":
return action.update.notifications?.[1] ?? state;
case "RESET":
return {};
default:

View file

@ -1,4 +1,4 @@
import { MessageObject } from "../../context/revoltjs/util";
import type { MessageObject } from "../../context/revoltjs/util";
export enum QueueStatus {
SENDING = "sending",

View file

@ -1,4 +1,4 @@
import { Core } from "revolt.js/dist/api/objects";
import type { Core } from "revolt.js/dist/api/objects";
export type ConfigAction =
| { type: undefined }

View file

@ -1,7 +1,7 @@
import { filter } from ".";
import { SyncUpdateAction } from "./sync";
import { Sounds } from "../../assets/sounds/Audio";
import { Theme, ThemeOptions } from "../../context/Theme";
import type { SyncUpdateAction } from "./sync";
import type { Sounds } from "../../assets/sounds/Audio";
import type { Theme, ThemeOptions } from "../../context/Theme";
import { setEmojiPack } from "../../components/common/Emoji";
export type SoundOptions = {

View file

@ -1,7 +1,7 @@
import { AppearanceOptions } from "./settings";
import { Language } from "../../context/Locale";
import { ThemeOptions } from "../../context/Theme";
import { Notifications } from "./notifications";
import type { AppearanceOptions } from "./settings";
import type { Language } from "../../context/Locale";
import type { ThemeOptions } from "../../context/Theme";
import type { Notifications } from "./notifications";
export type SyncKeys = "theme" | "appearance" | "locale" | "notifications";

View file

@ -1,4 +1,4 @@
import { Sync } from "revolt.js/dist/api/objects";
import type { Sync } from "revolt.js/dist/api/objects";
export interface Unreads {
[key: string]: Partial<Omit<Sync.ChannelUnread, "_id">>;

View file

@ -3,6 +3,9 @@ import { precacheAndRoute } from 'workbox-precaching'
import { Server } from 'revolt.js/dist/api/objects'
import { Channel, Message, User } from 'revolt.js'
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
@ -34,12 +37,18 @@ function decodeTime(id: string) {
return time;
}
const base_url = `https://autumn.revolt.chat`;
self.addEventListener("push", event => {
async function process() {
if (event.data === null) return;
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;
try {
// 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;
if (data.attachments) {
let attachment = data.attachments[0];
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) {
case "SavedMessages": break;
case "DirectMessage": title = `@${username}`; break;
@ -97,7 +111,7 @@ self.addEventListener("push", event => {
}
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,
body: typeof data.content === "string" ? data.content : JSON.stringify(data.content),
timestamp: decodeTime(data._id),