From 128e596c275cf35229a8a9a7fe7272c896ffc5b5 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Mon, 29 Sep 2025 16:38:07 -0500 Subject: [PATCH] muting channels --- src/webpage/channel.ts | 125 ++++++++++++++++++++++++++++++++++++--- src/webpage/guild.ts | 7 ++- src/webpage/jsontypes.ts | 8 ++- src/webpage/style.css | 8 +++ translations/en.json | 4 ++ 5 files changed, 139 insertions(+), 13 deletions(-) diff --git a/src/webpage/channel.ts b/src/webpage/channel.ts index f02c91c..c7fb82f 100644 --- a/src/webpage/channel.ts +++ b/src/webpage/channel.ts @@ -15,6 +15,7 @@ import { filejson, messageCreateJson, messagejson, + mute_config, readyjson, startTypingjson, } from "./jsontypes.js"; @@ -66,16 +67,14 @@ class Channel extends SnowFlake { voice?: Voice; bitrate: number = 128000; - muted: boolean = false; - mute_config = {selected_time_window: -1, end_time: 0}; + mute_config: mute_config | null = {selected_time_window: -1, end_time: 0}; handleUserOverrides(settings: { message_notifications: number; muted: boolean; - mute_config: {selected_time_window: number; end_time: number}; + mute_config: mute_config | null; channel_id: string; }) { this.message_notifications = settings.message_notifications; - this.muted = settings.muted; this.mute_config = settings.mute_config; } static setupcontextmenu() { @@ -102,11 +101,33 @@ class Channel extends SnowFlake { this.contextmenu.addSeperator(); //TODO notifcations icon this.contextmenu.addButton( - () => I18n.getTranslation("guild.notifications"), + () => I18n.guild.notifications(), function () { this.setnotifcation(); }, ); + this.contextmenu.addButton( + () => I18n.channel.mute(), + function () { + this.muteChannel(); + }, + { + visable: function () { + return !this.muted; + }, + }, + ); + this.contextmenu.addButton( + () => I18n.channel.unmute(), + function () { + this.unmuteChannel(); + }, + { + visable: function () { + return this.muted; + }, + }, + ); this.contextmenu.addButton( () => I18n.getTranslation("channel.settings"), @@ -149,6 +170,73 @@ class Channel extends SnowFlake { }, ); } + unmuteChannel() { + const mute_config = { + selected_time_window: -1, + end_time: 0, + }; + fetch(this.info.api + "/users/@me/guilds/" + this.guild.id + "/settings", { + method: "PATCH", + headers: this.headers, + body: JSON.stringify({ + channel_overrides: { + [this.id]: { + message_notifications: this.mentions, + muted: true, + mute_config, + channel_id: this.id, + }, + }, + }), + }); + this.mute_config = mute_config; + this.html?.deref()?.classList.remove("muted"); + this.unreads(); + this.guild.unreads(); + } + muteChannel() { + const dio = new Dialog(I18n.channel.mute()); + const opt = dio.options; + let time = 1800; + opt.addSelect( + I18n.muteDuration(), + () => {}, + ["30m", "1h", "6h", "12h", "1d", "7d", "30d", "never"].map((e) => + I18n.getTranslation("inviteOptions." + e), + ), + ).onchange = (e) => { + time = [1800, 3600, 21600, 43200, 86400, 604800, 2592000, 1 << 30][e]; + }; + opt.addButtonInput("", I18n.submit(), () => { + const mute_config = { + selected_time_window: time, + end_time: Math.floor(new Date(Date.now() + time * 1000).getTime()), + }; + fetch(this.info.api + "/users/@me/guilds/" + this.guild.id + "/settings", { + method: "PATCH", + headers: this.headers, + body: JSON.stringify({ + channel_overrides: { + [this.id]: { + message_notifications: this.mentions, + muted: false, + mute_config, + channel_id: this.id, + }, + }, + }), + }); + this.mute_config = mute_config; + this.html?.deref()?.classList.add("muted"); + dio.hide(); + this.unreads(); + this.guild.unreads(); + }); + dio.show(); + } + get muted() { + return !!this.mute_config && new Date(this.mute_config.end_time).getTime() > Date.now(); + } createInvite() { const div = document.createElement("div"); div.classList.add("invitediv"); @@ -471,6 +559,7 @@ class Channel extends SnowFlake { } } get hasunreads(): boolean { + if (this.muted) return false; if (!this.hasPermission("VIEW_CHANNEL")) { return false; } @@ -566,6 +655,16 @@ class Channel extends SnowFlake { voiceUsers = new WeakRef(document.createElement("div")); createguildHTML(admin = false): HTMLDivElement { const div = document.createElement("div"); + + if (this.muted) { + div.classList.add("muted"); + setTimeout( + () => { + div.classList.remove("muted"); + }, + Math.min((this.mute_config?.end_time as number) - Date.now(), 2147483647), + ); + } this.html = new WeakRef(div); if (!this.visable) { let quit = true; @@ -662,6 +761,7 @@ class Channel extends SnowFlake { } const button = document.createElement("button"); button.classList.add("channelbutton"); + div.append(button); const myhtml = document.createElement("span"); myhtml.classList.add("ellipsis"); @@ -2349,10 +2449,17 @@ class Channel extends SnowFlake { if (this.localuser.lookingguild?.prevchannel === this && document.hasFocus()) { return; } - if (this.notification === "all") { - this.notify(messagez); - } else if (this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)) { - this.notify(messagez); + if (!this.muted) { + if ( + !this.guild.mute_config || + new Date(this.guild.mute_config.end_time).getTime() < Date.now() + ) { + if (this.notification === "all") { + this.notify(messagez); + } else if (this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)) { + this.notify(messagez); + } + } } } notititle(message: Message): string { diff --git a/src/webpage/guild.ts b/src/webpage/guild.ts index 367d26a..6ad4e9e 100644 --- a/src/webpage/guild.ts +++ b/src/webpage/guild.ts @@ -16,6 +16,7 @@ import { extendedProperties, banObj, templateSkim, + mute_config, } from "./jsontypes.js"; import {User} from "./user.js"; import {I18n} from "./i18n.js"; @@ -1295,18 +1296,19 @@ class Guild extends SnowFlake { set perminfo(e) { this.localuser.perminfo.guilds[this.id] = e; } + mute_config!: mute_config | null; notisetting(settings: { channel_overrides: { message_notifications: number; muted: boolean; - mute_config: {selected_time_window: number; end_time: number}; + mute_config: mute_config; channel_id: string; }[]; message_notifications: any; flags?: number; hide_muted_channels?: boolean; mobile_push?: boolean; - mute_config?: null; + mute_config: null | mute_config; mute_scheduled_events?: boolean; muted?: boolean; notify_highlights?: number; @@ -1315,6 +1317,7 @@ class Guild extends SnowFlake { version?: number; guild_id?: string; }) { + this.mute_config = this.mute_config; this.message_notifications = settings.message_notifications; for (const override of settings.channel_overrides) { const channel = this.localuser.channelids.get(override.channel_id); diff --git a/src/webpage/jsontypes.ts b/src/webpage/jsontypes.ts index 9123498..91080cb 100644 --- a/src/webpage/jsontypes.ts +++ b/src/webpage/jsontypes.ts @@ -67,14 +67,14 @@ interface readyjson { channel_overrides: { message_notifications: number; muted: boolean; - mute_config: {selected_time_window: number; end_time: number}; + mute_config: mute_config | null; channel_id: string; }[]; message_notifications: number; flags: number; hide_muted_channels: boolean; mobile_push: boolean; - mute_config: null; + mute_config: mute_config | null; mute_scheduled_events: boolean; muted: boolean; notify_highlights: number; @@ -122,6 +122,10 @@ interface readyjson { }; }; } +export interface mute_config { + selected_time_window: number; + end_time: number; +} export interface guildFolder { color: number; guild_ids: string[]; diff --git a/src/webpage/style.css b/src/webpage/style.css index e1c1881..c356546 100644 --- a/src/webpage/style.css +++ b/src/webpage/style.css @@ -1318,6 +1318,14 @@ span.instanceStatus { flex-direction: column; margin-bottom: 2px; position: relative; + &.muted { + span { + color: color-mix(in srgb, var(--primary-text-soft), transparent); + &.svgicon { + background: color-mix(in srgb, var(--primary-text-soft), transparent); + } + } + } } .channelbutton { height: 2em; diff --git a/translations/en.json b/translations/en.json index d2d3a87..4f8cfb2 100644 --- a/translations/en.json +++ b/translations/en.json @@ -186,6 +186,7 @@ "joinedMember":"Joined $1: $2" }, "searchGifs": "Search Tenor", + "muteDuration":"Unmute in:", "channel": { "creating": "Creating channel", "name": "Channel", @@ -197,6 +198,8 @@ "settingsFor": "Settings for $1", "voice": "Voice", "text": "Text", + "mute":"Mute Channel", + "unmute":"Unmute Channel", "announcement": "Announcements", "name:": "Name:", "topic:": "Topic:", @@ -335,6 +338,7 @@ "copyId": "Copy guild id", "markRead": "Mark as read", "notifications": "Notifications", + "mute":"Mute Guild", "leave": "Leave guild", "settings": "Settings", "delete": "Delete guild",