/* * Vencord, a modification for Discord's desktop app * Copyright (c) 2022 Vendicated and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import ErrorBoundary from "@components/ErrorBoundary"; import { LazyComponent } from "@utils/misc"; import { formatDuration } from "@utils/text"; import { find, findByCode, findByPropsLazy } from "@webpack"; import { FluxDispatcher, GuildMemberStore, GuildStore, moment, Parser, SnowflakeUtils, Text, Timestamp, Tooltip } from "@webpack/common"; import { Channel } from "discord-types/general"; enum SortOrderTypes { LATEST_ACTIVITY = 0, CREATION_DATE = 1 } enum ForumLayoutTypes { DEFAULT = 0, LIST = 1, GRID = 2 } interface DefaultReaction { emojiId: string | null; emojiName: string | null; } interface Tag { id: string; name: string; emojiId: string | null; emojiName: string | null; moderated: boolean; } interface ExtendedChannel extends Channel { defaultThreadRateLimitPerUser?: number; defaultSortOrder?: SortOrderTypes | null; defaultForumLayout?: ForumLayoutTypes; defaultReactionEmoji?: DefaultReaction | null; availableTags?: Array; } enum ChannelTypes { GUILD_TEXT = 0, GUILD_VOICE = 2, GUILD_ANNOUNCEMENT = 5, GUILD_STAGE_VOICE = 13, GUILD_FORUM = 15 } enum VideoQualityModes { AUTO = 1, FULL = 2 } enum ChannelFlags { PINNED = 1 << 1, REQUIRE_TAG = 1 << 4 } const ChatScrollClasses = findByPropsLazy("auto", "content", "scrollerBase"); const TagComponent = LazyComponent(() => find(m => { if (typeof m !== "function") return false; const code = Function.prototype.toString.call(m); // Get the component which doesn't include increasedActivity logic return code.includes(".Messages.FORUM_TAG_A11Y_FILTER_BY_TAG") && !code.includes("increasedActivityPill"); })); const EmojiComponent = LazyComponent(() => findByCode('.jumboable?"jumbo":"default"')); // The component for the beggining of a channel, but we patched it so it only returns the allowed users and roles components for hidden channels const ChannelBeginHeader = LazyComponent(() => findByCode(".Messages.ROLE_REQUIRED_SINGLE_USER_MESSAGE")); const ChannelTypesToChannelNames = { [ChannelTypes.GUILD_TEXT]: "text", [ChannelTypes.GUILD_ANNOUNCEMENT]: "announcement", [ChannelTypes.GUILD_FORUM]: "forum", [ChannelTypes.GUILD_VOICE]: "voice", [ChannelTypes.GUILD_STAGE_VOICE]: "stage" }; const SortOrderTypesToNames = { [SortOrderTypes.LATEST_ACTIVITY]: "Latest activity", [SortOrderTypes.CREATION_DATE]: "Creation date" }; const ForumLayoutTypesToNames = { [ForumLayoutTypes.DEFAULT]: "Not set", [ForumLayoutTypes.LIST]: "List view", [ForumLayoutTypes.GRID]: "Gallery view" }; const VideoQualityModesToNames = { [VideoQualityModes.AUTO]: "Automatic", [VideoQualityModes.FULL]: "720p" }; // Icon from the modal when clicking a message link you don't have access to view const HiddenChannelLogo = "/assets/433e3ec4319a9d11b0cbe39342614982.svg"; function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) { const { type, topic, lastMessageId, defaultForumLayout, lastPinTimestamp, defaultAutoArchiveDuration, availableTags, id: channelId, rateLimitPerUser, defaultThreadRateLimitPerUser, defaultSortOrder, defaultReactionEmoji, bitrate, rtcRegion, videoQualityMode, permissionOverwrites } = channel; const membersToFetch: Array = []; const guildOwnerId = GuildStore.getGuild(channel.guild_id).ownerId; if (!GuildMemberStore.getMember(channel.guild_id, guildOwnerId)) membersToFetch.push(guildOwnerId); Object.values(permissionOverwrites).forEach(({ type, id: userId }) => { if (type === 1) { if (!GuildMemberStore.getMember(channel.guild_id, userId)) membersToFetch.push(userId); } }); if (membersToFetch.length > 0) { FluxDispatcher.dispatch({ type: "GUILD_MEMBERS_REQUEST", guildIds: [channel.guild_id], userIds: membersToFetch }); } return (
This is a hidden {ChannelTypesToChannelNames[type]} channel. {channel.isNSFW() && {({ onMouseLeave, onMouseEnter }) => ( )} }
{(!channel.isGuildVoice() && !channel.isGuildStageVoice()) && ( You can not see the {channel.isForumChannel() ? "posts" : "messages"} of this channel. {channel.isForumChannel() && topic && topic.length > 0 && "However you may see its guidelines:"} )} {channel.isForumChannel() && topic && topic.length > 0 && (
{Parser.parseTopic(topic, false, { channelId })}
)} {lastMessageId && Last {channel.isForumChannel() ? "post" : "message"} created: } {lastPinTimestamp && Last message pin: } {(rateLimitPerUser ?? 0) > 0 && Slowmode: {formatDuration(rateLimitPerUser!, "seconds")} } {(defaultThreadRateLimitPerUser ?? 0) > 0 && Default thread slowmode: {formatDuration(defaultThreadRateLimitPerUser!, "seconds")} } {((channel.isGuildVoice() || channel.isGuildStageVoice()) && bitrate != null) && Bitrate: {bitrate} bits } {rtcRegion !== undefined && Region: {rtcRegion ?? "Automatic"} } {(channel.isGuildVoice() || channel.isGuildStageVoice()) && Video quality mode: {VideoQualityModesToNames[videoQualityMode ?? VideoQualityModes.AUTO]} } {(defaultAutoArchiveDuration ?? 0) > 0 && Default inactivity duration before archiving {channel.isForumChannel() ? "posts" : "threads"}: {" " + formatDuration(defaultAutoArchiveDuration!, "minutes")} } {defaultForumLayout != null && Default layout: {ForumLayoutTypesToNames[defaultForumLayout]} } {defaultSortOrder != null && Default sort order: {SortOrderTypesToNames[defaultSortOrder]} } {defaultReactionEmoji != null &&
Default reaction emoji:
} {channel.hasFlag(ChannelFlags.REQUIRE_TAG) && Posts on this forum require a tag to be set. } {availableTags && availableTags.length > 0 &&
Available tags:
{availableTags.map(tag => )}
}
Allowed users and roles:
); } export default ErrorBoundary.wrap(HiddenChannelLockScreen);