/*
* 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 { Settings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { LazyComponent } from "@utils/react";
import { formatDuration } from "@utils/text";
import { find, findByPropsLazy } from "@webpack";
import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, moment, Parser, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common";
import type { Channel } from "discord-types/general";
import type { ComponentType } from "react";
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "../../permissionsViewer/components/RolesAndUsersPermissions";
import { sortPermissionOverwrites } from "../../permissionsViewer/utils";
import { settings, VIEW_CHANNEL } from "..";
const enum SortOrderTypes {
LATEST_ACTIVITY = 0,
CREATION_DATE = 1
}
const 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;
}
const enum ChannelTypes {
GUILD_TEXT = 0,
GUILD_VOICE = 2,
GUILD_ANNOUNCEMENT = 5,
GUILD_STAGE_VOICE = 13,
GUILD_FORUM = 15
}
const enum VideoQualityModes {
AUTO = 1,
FULL = 2
}
const enum ChannelFlags {
PINNED = 1 << 1,
REQUIRE_TAG = 1 << 4
}
let ChannelBeginHeader: ComponentType;
export function setChannelBeginHeaderComponent(component: ComponentType) {
ChannelBeginHeader = component;
}
const ChatScrollClasses = findByPropsLazy("auto", "content", "scrollerBase");
const ChatClasses = findByPropsLazy("chat", "content", "noChat", "chatContent");
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 EmojiParser = findByPropsLazy("convertSurrogateToName");
const EmojiUtils = findByPropsLazy("getURL", "buildEmojiReactionColorsPlatformed");
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 [viewAllowedUsersAndRoles, setViewAllowedUsersAndRoles] = useState(settings.store.defaultAllowedUsersAndRolesDropdownState);
const [permissions, setPermissions] = useState([]);
const {
type,
topic,
lastMessageId,
defaultForumLayout,
lastPinTimestamp,
defaultAutoArchiveDuration,
availableTags,
id: channelId,
rateLimitPerUser,
defaultThreadRateLimitPerUser,
defaultSortOrder,
defaultReactionEmoji,
bitrate,
rtcRegion,
videoQualityMode,
permissionOverwrites,
guild_id
} = channel;
useEffect(() => {
const membersToFetch: Array = [];
const guildOwnerId = GuildStore.getGuild(guild_id).ownerId;
if (!GuildMemberStore.getMember(guild_id, guildOwnerId)) membersToFetch.push(guildOwnerId);
Object.values(permissionOverwrites).forEach(({ type, id: userId }) => {
if (type === 1 && !GuildMemberStore.getMember(guild_id, userId)) {
membersToFetch.push(userId);
}
});
if (membersToFetch.length > 0) {
FluxDispatcher.dispatch({
type: "GUILD_MEMBERS_REQUEST",
guildIds: [guild_id],
userIds: membersToFetch
});
}
if (Settings.plugins.PermissionsViewer.enabled) {
setPermissions(sortPermissionOverwrites(Object.values(permissionOverwrites).map(overwrite => ({
type: overwrite.type as PermissionType,
id: overwrite.id,
overwriteAllow: overwrite.allow,
overwriteDeny: overwrite.deny
})), guild_id));
}
}, [channelId]);
return (
This is a {!PermissionStore.can(VIEW_CHANNEL, channel) ? "hidden" : "locked"} {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 && (