mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-01-10 18:06:22 +00:00
Merge branch 'dev' into NeverPausePreviews
This commit is contained in:
commit
12dfda93a3
21 changed files with 368 additions and 68 deletions
|
@ -44,6 +44,11 @@ export interface ProfileBadge {
|
||||||
position?: BadgePosition;
|
position?: BadgePosition;
|
||||||
/** The badge name to display, Discord uses this. Required for component badges */
|
/** The badge name to display, Discord uses this. Required for component badges */
|
||||||
key?: string;
|
key?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows dynamically returning multiple badges
|
||||||
|
*/
|
||||||
|
getBadges?(userInfo: BadgeUserArgs): ProfileBadge[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Badges = new Set<ProfileBadge>();
|
const Badges = new Set<ProfileBadge>();
|
||||||
|
@ -73,9 +78,16 @@ export function _getBadges(args: BadgeUserArgs) {
|
||||||
const badges = [] as ProfileBadge[];
|
const badges = [] as ProfileBadge[];
|
||||||
for (const badge of Badges) {
|
for (const badge of Badges) {
|
||||||
if (!badge.shouldShow || badge.shouldShow(args)) {
|
if (!badge.shouldShow || badge.shouldShow(args)) {
|
||||||
|
const b = badge.getBadges
|
||||||
|
? badge.getBadges(args).map(b => {
|
||||||
|
b.component &&= ErrorBoundary.wrap(b.component, { noop: true });
|
||||||
|
return b;
|
||||||
|
})
|
||||||
|
: [{ ...badge, ...args }];
|
||||||
|
|
||||||
badge.position === BadgePosition.START
|
badge.position === BadgePosition.START
|
||||||
? badges.unshift({ ...badge, ...args })
|
? badges.unshift(...b)
|
||||||
: badges.push({ ...badge, ...args });
|
: badges.push(...b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const donorBadges = (Plugins.BadgeAPI as unknown as typeof import("../plugins/_api/badges").default).getDonorBadges(args.userId);
|
const donorBadges = (Plugins.BadgeAPI as unknown as typeof import("../plugins/_api/badges").default).getDonorBadges(args.userId);
|
||||||
|
|
|
@ -31,10 +31,20 @@ export interface ExpandableHeaderProps {
|
||||||
headerText: string;
|
headerText: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
buttons?: React.ReactNode[];
|
buttons?: React.ReactNode[];
|
||||||
|
forceOpen?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExpandableHeader({ children, onMoreClick, buttons, moreTooltipText, defaultState = false, onDropDownClick, headerText }: ExpandableHeaderProps) {
|
export function ExpandableHeader({
|
||||||
const [showContent, setShowContent] = useState(defaultState);
|
children,
|
||||||
|
onMoreClick,
|
||||||
|
buttons,
|
||||||
|
moreTooltipText,
|
||||||
|
onDropDownClick,
|
||||||
|
headerText,
|
||||||
|
defaultState = false,
|
||||||
|
forceOpen = false,
|
||||||
|
}: ExpandableHeaderProps) {
|
||||||
|
const [showContent, setShowContent] = useState(defaultState || forceOpen);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -90,6 +100,7 @@ export function ExpandableHeader({ children, onMoreClick, buttons, moreTooltipTe
|
||||||
setShowContent(v => !v);
|
setShowContent(v => !v);
|
||||||
onDropDownClick?.(showContent);
|
onDropDownClick?.(showContent);
|
||||||
}}
|
}}
|
||||||
|
disabled={forceOpen}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
width="24"
|
width="24"
|
||||||
|
|
|
@ -290,3 +290,42 @@ export function NoEntrySignIcon(props: IconProps) {
|
||||||
</Icon>
|
</Icon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SafetyIcon(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
{...props}
|
||||||
|
className={classes(props.className, "vc-safety-icon")}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M4.27 5.22A2.66 2.66 0 0 0 3 7.5v2.3c0 5.6 3.3 10.68 8.42 12.95.37.17.79.17 1.16 0A14.18 14.18 0 0 0 21 9.78V7.5c0-.93-.48-1.78-1.27-2.27l-6.17-3.76a3 3 0 0 0-3.12 0L4.27 5.22ZM6 7.68l6-3.66V12H6.22C6.08 11.28 6 10.54 6 9.78v-2.1Zm6 12.01V12h5.78A11.19 11.19 0 0 1 12 19.7Z"
|
||||||
|
/>
|
||||||
|
</Icon>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NotesIcon(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
{...props}
|
||||||
|
className={classes(props.className, "vc-notes-icon")}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M8 3C7.44771 3 7 3.44772 7 4V5C7 5.55228 7.44772 6 8 6H16C16.5523 6 17 5.55228 17 5V4C17 3.44772 16.5523 3 16 3H15.1245C14.7288 3 14.3535 2.82424 14.1002 2.52025L13.3668 1.64018C13.0288 1.23454 12.528 1 12 1C11.472 1 10.9712 1.23454 10.6332 1.64018L9.8998 2.52025C9.64647 2.82424 9.27121 3 8.8755 3H8Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
fill="currentColor"
|
||||||
|
d="M19 4.49996V4.99996C19 6.65681 17.6569 7.99996 16 7.99996H8C6.34315 7.99996 5 6.65681 5 4.99996V4.49996C5 4.22382 4.77446 3.99559 4.50209 4.04109C3.08221 4.27826 2 5.51273 2 6.99996V19C2 20.6568 3.34315 22 5 22H19C20.6569 22 22 20.6568 22 19V6.99996C22 5.51273 20.9178 4.27826 19.4979 4.04109C19.2255 3.99559 19 4.22382 19 4.49996ZM8 12C7.44772 12 7 12.4477 7 13C7 13.5522 7.44772 14 8 14H16C16.5523 14 17 13.5522 17 13C17 12.4477 16.5523 12 16 12H8ZM7 17C7 16.4477 7.44772 16 8 16H13C13.5523 16 14 16.4477 14 17C14 17.5522 13.5523 18 13 18H8C7.44772 18 7 17.5522 7 17Z"
|
||||||
|
/>
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -136,6 +136,8 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
getBadges(props: { userId: string; user?: User; guildId: string; }) {
|
getBadges(props: { userId: string; user?: User; guildId: string; }) {
|
||||||
|
if (!props) return [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
props.userId ??= props.user?.id!;
|
props.userId ??= props.user?.id!;
|
||||||
|
|
||||||
|
|
|
@ -109,9 +109,9 @@ interface ProfileModalProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ColorPicker = findComponentByCodeLazy<ColorPickerProps>(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
|
const ColorPicker = findComponentByCodeLazy<ColorPickerProps>(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
|
||||||
const ProfileModal = findComponentByCodeLazy<ProfileModalProps>('"ProfileCustomizationPreview"');
|
const ProfileModal = findComponentByCodeLazy("isTryItOutFlow:", "pendingThemeColors:", "avatarDecorationOverride:", ".CUSTOM_STATUS");
|
||||||
|
|
||||||
const requireColorPicker = extractAndLoadChunksLazy(["USER_SETTINGS_PROFILE_COLOR_DEFAULT_BUTTON.format"], /createPromise:\(\)=>\i\.\i\("?(.+?)"?\).then\(\i\.bind\(\i,"?(.+?)"?\)\)/);
|
const requireColorPicker = extractAndLoadChunksLazy(["USER_SETTINGS_PROFILE_COLOR_DEFAULT_BUTTON.format"], /createPromise:\(\)=>\i\.\i(\("?.+?"?\)).then\(\i\.bind\(\i,"?(.+?)"?\)\)/);
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "FakeProfileThemes",
|
name: "FakeProfileThemes",
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default definePlugin({
|
||||||
find: ".Messages.MUTUAL_GUILDS_WITH_END_COUNT", // Note: the module is lazy-loaded
|
find: ".Messages.MUTUAL_GUILDS_WITH_END_COUNT", // Note: the module is lazy-loaded
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?<=\.tabBarItem.{0,50}MUTUAL_GUILDS.+?}\),)(?=.+?(\(0,\i\.jsxs?\)\(.{0,100}id:))/,
|
match: /(?<=\.tabBarItem.{0,50}MUTUAL_GUILDS.+?}\),)(?=.+?(\(0,\i\.jsxs?\)\(.{0,100}id:))/,
|
||||||
replace: '(arguments[0].user.bot||arguments[0].isCurrentUser)?null:$1"MUTUAL_GDMS",children:"Mutual Groups"}),'
|
replace: '$self.isBotOrSelf(arguments[0].user)?null:$1"MUTUAL_GDMS",children:"Mutual Groups"}),'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -58,9 +58,24 @@ export default definePlugin({
|
||||||
match: /(?<={user:(\i),onClose:(\i)}\);)(?=case \i\.\i\.MUTUAL_FRIENDS)/,
|
match: /(?<={user:(\i),onClose:(\i)}\);)(?=case \i\.\i\.MUTUAL_FRIENDS)/,
|
||||||
replace: "case \"MUTUAL_GDMS\":return $self.renderMutualGDMs({user: $1, onClose: $2});"
|
replace: "case \"MUTUAL_GDMS\":return $self.renderMutualGDMs({user: $1, onClose: $2});"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: ".MUTUAL_FRIENDS?(",
|
||||||
|
replacement: [
|
||||||
|
{
|
||||||
|
match: /(?<=onItemSelect:\i,children:)(\i)\.map/,
|
||||||
|
replace: "[...$1, ...($self.isBotOrSelf(arguments[0].user) ? [] : [{section:'MUTUAL_GDMS',text:'Mutual Groups'}])].map"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /\(0,\i\.jsx\)\(\i,\{items:\i,section:(\i)/,
|
||||||
|
replace: "$1==='MUTUAL_GDMS'?$self.renderMutualGDMs(arguments[0]):$&"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
isBotOrSelf: (user: User) => user.bot || user.id === UserStore.getCurrentUser().id,
|
||||||
|
|
||||||
renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => {
|
renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => {
|
||||||
const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => (
|
const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => (
|
||||||
<Clickable
|
<Clickable
|
||||||
|
|
|
@ -16,10 +16,17 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
findGroupChildrenByChildId,
|
||||||
|
NavContextMenuPatchCallback
|
||||||
|
} from "@api/ContextMenu";
|
||||||
import { definePluginSettings, migratePluginSettings } from "@api/Settings";
|
import { definePluginSettings, migratePluginSettings } from "@api/Settings";
|
||||||
|
import { CogWheel } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByCodeLazy, findByPropsLazy, mapMangledModuleLazy } from "@webpack";
|
import { findByCodeLazy, findByPropsLazy, mapMangledModuleLazy } from "@webpack";
|
||||||
|
import { Menu } from "@webpack/common";
|
||||||
|
import { Guild } from "discord-types/general";
|
||||||
|
|
||||||
const { updateGuildNotificationSettings } = findByPropsLazy("updateGuildNotificationSettings");
|
const { updateGuildNotificationSettings } = findByPropsLazy("updateGuildNotificationSettings");
|
||||||
const { toggleShowAllChannels } = mapMangledModuleLazy(".onboardExistingMember(", {
|
const { toggleShowAllChannels } = mapMangledModuleLazy(".onboardExistingMember(", {
|
||||||
|
@ -73,31 +80,21 @@ const settings = definePluginSettings({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
migratePluginSettings("NewGuildSettings", "MuteNewGuild");
|
const makeContextMenuPatch: (shouldAddIcon: boolean) => NavContextMenuPatchCallback = (shouldAddIcon: boolean) => (children, { guild }: { guild: Guild, onClose(): void; }) => {
|
||||||
export default definePlugin({
|
if (!guild) return;
|
||||||
name: "NewGuildSettings",
|
|
||||||
description: "Automatically mute new servers and change various other settings upon joining",
|
|
||||||
tags: ["MuteNewGuild", "mute", "server"],
|
|
||||||
authors: [Devs.Glitch, Devs.Nuckyz, Devs.carince, Devs.Mopi, Devs.GabiRP],
|
|
||||||
patches: [
|
|
||||||
{
|
|
||||||
find: ",acceptInvite(",
|
|
||||||
replacement: {
|
|
||||||
match: /INVITE_ACCEPT_SUCCESS.+?,(\i)=null!==.+?;/,
|
|
||||||
replace: (m, guildId) => `${m}$self.handleMute(${guildId});`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
find: "{joinGuild:",
|
|
||||||
replacement: {
|
|
||||||
match: /guildId:(\i),lurker:(\i).{0,20}}\)\);/,
|
|
||||||
replace: (m, guildId, lurker) => `${m}if(!${lurker})$self.handleMute(${guildId});`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
settings,
|
|
||||||
|
|
||||||
handleMute(guildId: string | null) {
|
const group = findGroupChildrenByChildId("privacy", children);
|
||||||
|
group?.push(
|
||||||
|
<Menu.MenuItem
|
||||||
|
label="Apply NewGuildSettings"
|
||||||
|
id="vc-newguildsettings-apply"
|
||||||
|
icon={shouldAddIcon ? CogWheel : void 0}
|
||||||
|
action={() => applyDefaultSettings(guild.id)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function applyDefaultSettings(guildId: string | null) {
|
||||||
if (guildId === "@me" || guildId === "null" || guildId == null) return;
|
if (guildId === "@me" || guildId === "null" || guildId == null) return;
|
||||||
updateGuildNotificationSettings(guildId,
|
updateGuildNotificationSettings(guildId,
|
||||||
{
|
{
|
||||||
|
@ -116,5 +113,35 @@ export default definePlugin({
|
||||||
if (settings.store.showAllChannels && isOptInEnabledForGuild(guildId)) {
|
if (settings.store.showAllChannels && isOptInEnabledForGuild(guildId)) {
|
||||||
toggleShowAllChannels(guildId);
|
toggleShowAllChannels(guildId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
migratePluginSettings("NewGuildSettings", "MuteNewGuild");
|
||||||
|
export default definePlugin({
|
||||||
|
name: "NewGuildSettings",
|
||||||
|
description: "Automatically mute new servers and change various other settings upon joining",
|
||||||
|
tags: ["MuteNewGuild", "mute", "server"],
|
||||||
|
authors: [Devs.Glitch, Devs.Nuckyz, Devs.carince, Devs.Mopi, Devs.GabiRP],
|
||||||
|
contextMenus: {
|
||||||
|
"guild-context": makeContextMenuPatch(false),
|
||||||
|
"guild-header-popout": makeContextMenuPatch(true)
|
||||||
|
},
|
||||||
|
patches: [
|
||||||
|
{
|
||||||
|
find: ",acceptInvite(",
|
||||||
|
replacement: {
|
||||||
|
match: /INVITE_ACCEPT_SUCCESS.+?,(\i)=null!==.+?;/,
|
||||||
|
replace: (m, guildId) => `${m}$self.applyDefaultSettings(${guildId});`
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "{joinGuild:",
|
||||||
|
replacement: {
|
||||||
|
match: /guildId:(\i),lurker:(\i).{0,20}}\)\);/,
|
||||||
|
replace: (m, guildId, lurker) => `${m}if(!${lurker})$self.applyDefaultSettings(${guildId});`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
settings,
|
||||||
|
applyDefaultSettings
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,7 +43,7 @@ const Classes = proxyLazyWebpack(() =>
|
||||||
))
|
))
|
||||||
) as Record<"roles" | "rolePill" | "rolePillBorder" | "desaturateUserColors" | "flex" | "alignCenter" | "justifyCenter" | "svg" | "background" | "dot" | "dotBorderColor" | "roleCircle" | "dotBorderBase" | "flex" | "alignCenter" | "justifyCenter" | "wrap" | "root" | "role" | "roleRemoveButton" | "roleDot" | "roleFlowerStar" | "roleRemoveIcon" | "roleRemoveIconFocused" | "roleVerifiedIcon" | "roleName" | "roleNameOverflow" | "actionButton" | "overflowButton" | "addButton" | "addButtonIcon" | "overflowRolesPopout" | "overflowRolesPopoutArrowWrapper" | "overflowRolesPopoutArrow" | "popoutBottom" | "popoutTop" | "overflowRolesPopoutHeader" | "overflowRolesPopoutHeaderIcon" | "overflowRolesPopoutHeaderText" | "roleIcon", string>;
|
) as Record<"roles" | "rolePill" | "rolePillBorder" | "desaturateUserColors" | "flex" | "alignCenter" | "justifyCenter" | "svg" | "background" | "dot" | "dotBorderColor" | "roleCircle" | "dotBorderBase" | "flex" | "alignCenter" | "justifyCenter" | "wrap" | "root" | "role" | "roleRemoveButton" | "roleDot" | "roleFlowerStar" | "roleRemoveIcon" | "roleRemoveIconFocused" | "roleVerifiedIcon" | "roleName" | "roleNameOverflow" | "actionButton" | "overflowButton" | "addButton" | "addButtonIcon" | "overflowRolesPopout" | "overflowRolesPopoutArrowWrapper" | "overflowRolesPopoutArrow" | "popoutBottom" | "popoutTop" | "overflowRolesPopoutHeader" | "overflowRolesPopoutHeaderIcon" | "overflowRolesPopoutHeaderText" | "roleIcon", string>;
|
||||||
|
|
||||||
function UserPermissionsComponent({ guild, guildMember, showBorder }: { guild: Guild; guildMember: GuildMember; showBorder: boolean; }) {
|
function UserPermissionsComponent({ guild, guildMember, showBorder, forceOpen = false }: { guild: Guild; guildMember: GuildMember; showBorder: boolean; forceOpen?: boolean; }) {
|
||||||
const stns = settings.use(["permissionsSortOrder"]);
|
const stns = settings.use(["permissionsSortOrder"]);
|
||||||
|
|
||||||
const [rolePermissions, userPermissions] = useMemo(() => {
|
const [rolePermissions, userPermissions] = useMemo(() => {
|
||||||
|
@ -95,6 +95,7 @@ function UserPermissionsComponent({ guild, guildMember, showBorder }: { guild: G
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ExpandableHeader
|
<ExpandableHeader
|
||||||
|
forceOpen={forceOpen}
|
||||||
headerText="Permissions"
|
headerText="Permissions"
|
||||||
moreTooltipText="Role Details"
|
moreTooltipText="Role Details"
|
||||||
onMoreClick={() =>
|
onMoreClick={() =>
|
||||||
|
|
|
@ -20,15 +20,22 @@ import "./styles.css";
|
||||||
|
|
||||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
import { SafetyIcon } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
import { classes } from "@utils/misc";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { ChannelStore, GuildMemberStore, GuildStore, Menu, PermissionsBits, UserStore } from "@webpack/common";
|
import { findByPropsLazy } from "@webpack";
|
||||||
|
import { Button, ChannelStore, Dialog, GuildMemberStore, GuildStore, Menu, PermissionsBits, Popout, TooltipContainer, UserStore } from "@webpack/common";
|
||||||
import type { Guild, GuildMember } from "discord-types/general";
|
import type { Guild, GuildMember } from "discord-types/general";
|
||||||
|
|
||||||
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions";
|
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions";
|
||||||
import UserPermissions from "./components/UserPermissions";
|
import UserPermissions from "./components/UserPermissions";
|
||||||
import { getSortedRoles, sortPermissionOverwrites } from "./utils";
|
import { getSortedRoles, sortPermissionOverwrites } from "./utils";
|
||||||
|
|
||||||
|
const PopoutClasses = findByPropsLazy("container", "scroller", "list");
|
||||||
|
const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "text");
|
||||||
|
|
||||||
export const enum PermissionsSortOrder {
|
export const enum PermissionsSortOrder {
|
||||||
HighestRole,
|
HighestRole,
|
||||||
LowestRole
|
LowestRole
|
||||||
|
@ -168,10 +175,45 @@ export default definePlugin({
|
||||||
match: /showBorder:(.{0,60})}\),(?<=guild:(\i),guildMember:(\i),.+?)/,
|
match: /showBorder:(.{0,60})}\),(?<=guild:(\i),guildMember:(\i),.+?)/,
|
||||||
replace: (m, showBoder, guild, guildMember) => `${m}$self.UserPermissions(${guild},${guildMember},${showBoder}),`
|
replace: (m, showBoder, guild, guildMember) => `${m}$self.UserPermissions(${guild},${guildMember},${showBoder}),`
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: ".VIEW_ALL_ROLES,",
|
||||||
|
replacement: {
|
||||||
|
match: /children:"\+"\.concat\(\i\.length-\i\.length\).{0,20}\}\),/,
|
||||||
|
replace: "$&$self.ViewPermissionsButton(arguments[0]),"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
UserPermissions: (guild: Guild, guildMember: GuildMember | undefined, showBoder: boolean) => !!guildMember && <UserPermissions guild={guild} guildMember={guildMember} showBorder={showBoder} />,
|
UserPermissions: (guild: Guild, guildMember: GuildMember | undefined, showBorder: boolean) =>
|
||||||
|
!!guildMember && <UserPermissions guild={guild} guildMember={guildMember} showBorder={showBorder} />,
|
||||||
|
|
||||||
|
ViewPermissionsButton: ErrorBoundary.wrap(({ guild, guildMember }: { guild: Guild; guildMember: GuildMember; }) => (
|
||||||
|
<Popout
|
||||||
|
position="bottom"
|
||||||
|
align="center"
|
||||||
|
renderPopout={() => (
|
||||||
|
<Dialog className={PopoutClasses.container} style={{ width: "500px" }}>
|
||||||
|
<UserPermissions guild={guild} guildMember={guildMember} showBorder forceOpen />
|
||||||
|
</Dialog>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{popoutProps => (
|
||||||
|
<TooltipContainer text="View Permissions">
|
||||||
|
<Button
|
||||||
|
{...popoutProps}
|
||||||
|
color={Button.Colors.CUSTOM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
size={Button.Sizes.NONE}
|
||||||
|
innerClassName={classes(RoleButtonClasses.buttonInner, RoleButtonClasses.icon)}
|
||||||
|
className={classes(RoleButtonClasses.button, RoleButtonClasses.icon, "vc-permviewer-role-button")}
|
||||||
|
>
|
||||||
|
<SafetyIcon height="16" width="16" />
|
||||||
|
</Button>
|
||||||
|
</TooltipContainer>
|
||||||
|
)}
|
||||||
|
</Popout>
|
||||||
|
), { noop: true }),
|
||||||
|
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
"user-context": makeContextMenuPatch("roles", MenuItemParentType.User),
|
"user-context": makeContextMenuPatch("roles", MenuItemParentType.User),
|
||||||
|
|
|
@ -149,3 +149,21 @@
|
||||||
.vc-permviewer-perms-perms-item .vc-info-icon:hover {
|
.vc-permviewer-perms-perms-item .vc-info-icon:hover {
|
||||||
color: var(--interactive-active);
|
color: var(--interactive-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy pasted from discord cause impossible to webpack find */
|
||||||
|
.vc-permviewer-role-button {
|
||||||
|
border-radius: var(--radius-xs);
|
||||||
|
background: var(--bg-mod-faint);
|
||||||
|
color: var(--interactive-normal);
|
||||||
|
border: 1px solid var(--border-faint);
|
||||||
|
/* stylelint-disable-next-line value-no-vendor-prefix */
|
||||||
|
width: -moz-fit-content;
|
||||||
|
width: fit-content;
|
||||||
|
height: 24px;
|
||||||
|
padding: 4px
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-profile-theme .vc-permviewer-role-button {
|
||||||
|
background: rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-6));
|
||||||
|
border-color: var(--profile-body-border-color)
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { addBadge, BadgePosition, ProfileBadge, removeBadge } from "@api/Badges";
|
import "./style.css";
|
||||||
|
|
||||||
|
import { addBadge, BadgePosition, BadgeUserArgs, ProfileBadge, removeBadge } from "@api/Badges";
|
||||||
import { addDecorator, removeDecorator } from "@api/MemberListDecorators";
|
import { addDecorator, removeDecorator } from "@api/MemberListDecorators";
|
||||||
import { addDecoration, removeDecoration } from "@api/MessageDecorations";
|
import { addDecoration, removeDecoration } from "@api/MessageDecorations";
|
||||||
import { Settings } from "@api/Settings";
|
import { Settings } from "@api/Settings";
|
||||||
|
@ -27,7 +29,20 @@ import { findByPropsLazy, findStoreLazy } from "@webpack";
|
||||||
import { PresenceStore, Tooltip, UserStore } from "@webpack/common";
|
import { PresenceStore, Tooltip, UserStore } from "@webpack/common";
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
|
|
||||||
const SessionsStore = findStoreLazy("SessionsStore");
|
export interface Session {
|
||||||
|
sessionId: string;
|
||||||
|
status: string;
|
||||||
|
active: boolean;
|
||||||
|
clientInfo: {
|
||||||
|
version: number;
|
||||||
|
os: string;
|
||||||
|
client: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const SessionsStore = findStoreLazy("SessionsStore") as {
|
||||||
|
getSessions(): Record<string, Session>;
|
||||||
|
};
|
||||||
|
|
||||||
function Icon(path: string, opts?: { viewBox?: string; width?: number; height?: number; }) {
|
function Icon(path: string, opts?: { viewBox?: string; width?: number; height?: number; }) {
|
||||||
return ({ color, tooltip, small }: { color: string; tooltip: string; small: boolean; }) => (
|
return ({ color, tooltip, small }: { color: string; tooltip: string; small: boolean; }) => (
|
||||||
|
@ -67,15 +82,11 @@ const PlatformIcon = ({ platform, status, small }: { platform: Platform, status:
|
||||||
return <Icon color={StatusUtils.useStatusFillColor(status)} tooltip={tooltip} small={small} />;
|
return <Icon color={StatusUtils.useStatusFillColor(status)} tooltip={tooltip} small={small} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStatus = (id: string): Record<Platform, string> => PresenceStore.getState()?.clientStatuses?.[id];
|
function ensureOwnStatus(user: User) {
|
||||||
|
|
||||||
const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, small = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; small?: boolean; }) => {
|
|
||||||
if (!user || user.bot) return null;
|
|
||||||
|
|
||||||
if (user.id === UserStore.getCurrentUser().id) {
|
if (user.id === UserStore.getCurrentUser().id) {
|
||||||
const sessions = SessionsStore.getSessions();
|
const sessions = SessionsStore.getSessions();
|
||||||
if (typeof sessions !== "object") return null;
|
if (typeof sessions !== "object") return null;
|
||||||
const sortedSessions = Object.values(sessions).sort(({ status: a }: any, { status: b }: any) => {
|
const sortedSessions = Object.values(sessions).sort(({ status: a }, { status: b }) => {
|
||||||
if (a === b) return 0;
|
if (a === b) return 0;
|
||||||
if (a === "online") return 1;
|
if (a === "online") return 1;
|
||||||
if (b === "online") return -1;
|
if (b === "online") return -1;
|
||||||
|
@ -84,7 +95,7 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
const ownStatus = Object.values(sortedSessions).reduce((acc: any, curr: any) => {
|
const ownStatus = Object.values(sortedSessions).reduce((acc, curr) => {
|
||||||
if (curr.clientInfo.client !== "unknown")
|
if (curr.clientInfo.client !== "unknown")
|
||||||
acc[curr.clientInfo.client] = curr.status;
|
acc[curr.clientInfo.client] = curr.status;
|
||||||
return acc;
|
return acc;
|
||||||
|
@ -93,6 +104,37 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
|
||||||
const { clientStatuses } = PresenceStore.getState();
|
const { clientStatuses } = PresenceStore.getState();
|
||||||
clientStatuses[UserStore.getCurrentUser().id] = ownStatus;
|
clientStatuses[UserStore.getCurrentUser().id] = ownStatus;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] {
|
||||||
|
const user = UserStore.getUser(userId);
|
||||||
|
|
||||||
|
if (!user || user.bot) return [];
|
||||||
|
|
||||||
|
ensureOwnStatus(user);
|
||||||
|
|
||||||
|
const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record<Platform, string>;
|
||||||
|
if (!status) return [];
|
||||||
|
|
||||||
|
return Object.entries(status).map(([platform, status]) => ({
|
||||||
|
component: () => (
|
||||||
|
<span className="vc-platform-indicator">
|
||||||
|
<PlatformIcon
|
||||||
|
key={platform}
|
||||||
|
platform={platform as Platform}
|
||||||
|
status={status}
|
||||||
|
small={false}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
key: `vc-platform-indicator-${platform}`
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, small = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; small?: boolean; }) => {
|
||||||
|
if (!user || user.bot) return null;
|
||||||
|
|
||||||
|
ensureOwnStatus(user);
|
||||||
|
|
||||||
const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record<Platform, string>;
|
const status = PresenceStore.getState()?.clientStatuses?.[user.id] as Record<Platform, string>;
|
||||||
if (!status) return null;
|
if (!status) return null;
|
||||||
|
@ -112,17 +154,10 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
|
||||||
<span
|
<span
|
||||||
className="vc-platform-indicator"
|
className="vc-platform-indicator"
|
||||||
style={{
|
style={{
|
||||||
display: "inline-flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
marginLeft: wantMargin ? 4 : 0,
|
marginLeft: wantMargin ? 4 : 0,
|
||||||
verticalAlign: "top",
|
|
||||||
position: "relative",
|
|
||||||
top: wantTopMargin ? 2 : 0,
|
top: wantTopMargin ? 2 : 0,
|
||||||
padding: !wantMargin ? 1 : 0,
|
|
||||||
gap: 2
|
gap: 2
|
||||||
}}
|
}}
|
||||||
|
|
||||||
>
|
>
|
||||||
{icons}
|
{icons}
|
||||||
</span>
|
</span>
|
||||||
|
@ -130,10 +165,8 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
|
||||||
};
|
};
|
||||||
|
|
||||||
const badge: ProfileBadge = {
|
const badge: ProfileBadge = {
|
||||||
component: p => <PlatformIndicator {...p} user={UserStore.getUser(p.userId)} wantMargin={false} />,
|
getBadges,
|
||||||
position: BadgePosition.START,
|
position: BadgePosition.START,
|
||||||
shouldShow: userInfo => !!Object.keys(getStatus(userInfo.userId) ?? {}).length,
|
|
||||||
key: "indicator"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const indicatorLocations = {
|
const indicatorLocations = {
|
||||||
|
|
7
src/plugins/platformIndicators/style.css
Normal file
7
src/plugins/platformIndicators/style.css
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
.vc-platform-indicator {
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
vertical-align: top;
|
||||||
|
position: relative;
|
||||||
|
}
|
|
@ -13,13 +13,12 @@ import { Flex, Menu } from "@webpack/common";
|
||||||
const DefaultEngines = {
|
const DefaultEngines = {
|
||||||
Google: "https://www.google.com/search?q=",
|
Google: "https://www.google.com/search?q=",
|
||||||
DuckDuckGo: "https://duckduckgo.com/",
|
DuckDuckGo: "https://duckduckgo.com/",
|
||||||
|
Brave: "https://search.brave.com/search?q=",
|
||||||
Bing: "https://www.bing.com/search?q=",
|
Bing: "https://www.bing.com/search?q=",
|
||||||
Yahoo: "https://search.yahoo.com/search?p=",
|
Yahoo: "https://search.yahoo.com/search?p=",
|
||||||
GitHub: "https://github.com/search?q=",
|
|
||||||
Kagi: "https://kagi.com/search?q=",
|
|
||||||
Yandex: "https://yandex.com/search/?text=",
|
Yandex: "https://yandex.com/search/?text=",
|
||||||
AOL: "https://search.aol.com/aol/search?q=",
|
GitHub: "https://github.com/search?q=",
|
||||||
Baidu: "https://www.baidu.com/s?wd=",
|
Reddit: "https://www.reddit.com/search?q=",
|
||||||
Wikipedia: "https://wikipedia.org/w/index.php?search=",
|
Wikipedia: "https://wikipedia.org/w/index.php?search=",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ function makeSearchItem(src: string) {
|
||||||
key="search-text"
|
key="search-text"
|
||||||
id="vc-search-text"
|
id="vc-search-text"
|
||||||
>
|
>
|
||||||
{Object.keys(Engines).map((engine, i) => {
|
{Object.keys(Engines).map(engine => {
|
||||||
const key = "vc-search-content-" + engine;
|
const key = "vc-search-content-" + engine;
|
||||||
return (
|
return (
|
||||||
<Menu.MenuItem
|
<Menu.MenuItem
|
||||||
|
@ -70,7 +69,7 @@ function makeSearchItem(src: string) {
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
height={16}
|
height={16}
|
||||||
width={16}
|
width={16}
|
||||||
src={`https://www.google.com/s2/favicons?domain=${Engines[engine]}`}
|
src={`https://www.google.com/s2/favicons?domain=${Engines[engine]}&sz=64`}
|
||||||
/>
|
/>
|
||||||
{engine}
|
{engine}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { cl } from "../utils";
|
||||||
import ReviewComponent from "./ReviewComponent";
|
import ReviewComponent from "./ReviewComponent";
|
||||||
import ReviewsView, { ReviewsInputComponent } from "./ReviewsView";
|
import ReviewsView, { ReviewsInputComponent } from "./ReviewsView";
|
||||||
|
|
||||||
function Modal({ modalProps, discordId, name }: { modalProps: any; discordId: string; name: string; }) {
|
function Modal({ modalProps, modalKey, discordId, name }: { modalProps: any; modalKey: string, discordId: string; name: string; }) {
|
||||||
const [data, setData] = useState<Response>();
|
const [data, setData] = useState<Response>();
|
||||||
const [signal, refetch] = useForceUpdater(true);
|
const [signal, refetch] = useForceUpdater(true);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
|
@ -76,6 +76,7 @@ function Modal({ modalProps, discordId, name }: { modalProps: any; discordId: st
|
||||||
discordId={discordId}
|
discordId={discordId}
|
||||||
name={name}
|
name={name}
|
||||||
refetch={refetch}
|
refetch={refetch}
|
||||||
|
modalKey={modalKey}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!!reviewCount && (
|
{!!reviewCount && (
|
||||||
|
@ -95,11 +96,14 @@ function Modal({ modalProps, discordId, name }: { modalProps: any; discordId: st
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openReviewsModal(discordId: string, name: string) {
|
export function openReviewsModal(discordId: string, name: string) {
|
||||||
|
const modalKey = "vc-rdb-modal-" + Date.now();
|
||||||
|
|
||||||
openModal(props => (
|
openModal(props => (
|
||||||
<Modal
|
<Modal
|
||||||
|
modalKey={modalKey}
|
||||||
modalProps={props}
|
modalProps={props}
|
||||||
discordId={discordId}
|
discordId={discordId}
|
||||||
name={name}
|
name={name}
|
||||||
/>
|
/>
|
||||||
));
|
), { modalKey });
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,9 @@ function ReviewList({ refetch, reviews, hideOwnReview, profileId }: { refetch():
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: { discordId: string, name: string; isAuthor: boolean; refetch(): void; }) {
|
export function ReviewsInputComponent(
|
||||||
|
{ discordId, isAuthor, refetch, name, modalKey }: { discordId: string, name: string; isAuthor: boolean; refetch(): void; modalKey?: string; }
|
||||||
|
) {
|
||||||
const { token } = Auth;
|
const { token } = Auth;
|
||||||
const editorRef = useRef<any>(null);
|
const editorRef = useRef<any>(null);
|
||||||
const inputType = ChatInputTypes.FORM;
|
const inputType = ChatInputTypes.FORM;
|
||||||
|
@ -148,6 +150,7 @@ export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: {
|
||||||
type={inputType}
|
type={inputType}
|
||||||
disableThemedBackground={true}
|
disableThemedBackground={true}
|
||||||
setEditorRef={ref => editorRef.current = ref}
|
setEditorRef={ref => editorRef.current = ref}
|
||||||
|
parentModalKey={modalKey}
|
||||||
textValue=""
|
textValue=""
|
||||||
onSubmit={
|
onSubmit={
|
||||||
async res => {
|
async res => {
|
||||||
|
|
|
@ -21,10 +21,12 @@ import "./style.css";
|
||||||
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { ExpandableHeader } from "@components/ExpandableHeader";
|
import { ExpandableHeader } from "@components/ExpandableHeader";
|
||||||
import { OpenExternalIcon } from "@components/Icons";
|
import { NotesIcon, OpenExternalIcon } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
import { classes } from "@utils/misc";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { Alerts, Menu, Parser, useState } from "@webpack/common";
|
import { findByPropsLazy } from "@webpack";
|
||||||
|
import { Alerts, Button, Menu, Parser, TooltipContainer, useState } from "@webpack/common";
|
||||||
import { Guild, User } from "discord-types/general";
|
import { Guild, User } from "discord-types/general";
|
||||||
|
|
||||||
import { Auth, initAuth, updateAuth } from "./auth";
|
import { Auth, initAuth, updateAuth } from "./auth";
|
||||||
|
@ -35,6 +37,9 @@ import { getCurrentUserInfo, readNotification } from "./reviewDbApi";
|
||||||
import { settings } from "./settings";
|
import { settings } from "./settings";
|
||||||
import { showToast } from "./utils";
|
import { showToast } from "./utils";
|
||||||
|
|
||||||
|
const PopoutClasses = findByPropsLazy("container", "scroller", "list");
|
||||||
|
const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "text");
|
||||||
|
|
||||||
const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => {
|
const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => {
|
||||||
if (!guild) return;
|
if (!guild) return;
|
||||||
children.push(
|
children.push(
|
||||||
|
@ -69,7 +74,8 @@ export default definePlugin({
|
||||||
"guild-header-popout": guildPopoutPatch,
|
"guild-header-popout": guildPopoutPatch,
|
||||||
"guild-context": guildPopoutPatch,
|
"guild-context": guildPopoutPatch,
|
||||||
"user-context": userContextPatch,
|
"user-context": userContextPatch,
|
||||||
"user-profile-actions": userContextPatch
|
"user-profile-actions": userContextPatch,
|
||||||
|
"user-profile-overflow-menu": userContextPatch
|
||||||
},
|
},
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
|
@ -79,6 +85,13 @@ export default definePlugin({
|
||||||
match: /user:(\i),setNote:\i,canDM.+?\}\)/,
|
match: /user:(\i),setNote:\i,canDM.+?\}\)/,
|
||||||
replace: "$&,$self.getReviewsComponent($1)"
|
replace: "$&,$self.getReviewsComponent($1)"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: ".VIEW_FULL_PROFILE,",
|
||||||
|
replacement: {
|
||||||
|
match: /(?<=\.BITE_SIZE,children:\[)\(0,\i\.jsx\)\(\i\.\i,\{user:(\i),/,
|
||||||
|
replace: "$self.BiteSizeReviewsButton({user:$1}),$&"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -159,5 +172,22 @@ export default definePlugin({
|
||||||
/>
|
/>
|
||||||
</ExpandableHeader>
|
</ExpandableHeader>
|
||||||
);
|
);
|
||||||
}, { message: "Failed to render Reviews" })
|
}, { message: "Failed to render Reviews" }),
|
||||||
|
|
||||||
|
BiteSizeReviewsButton: ErrorBoundary.wrap(({ user }: { user: User; }) => {
|
||||||
|
return (
|
||||||
|
<TooltipContainer text="View Reviews">
|
||||||
|
<Button
|
||||||
|
onClick={() => openReviewsModal(user.id, user.username)}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
size={Button.Sizes.NONE}
|
||||||
|
color={RoleButtonClasses.color}
|
||||||
|
className={classes(RoleButtonClasses.button, RoleButtonClasses.banner)}
|
||||||
|
innerClassName={classes(RoleButtonClasses.buttonInner, RoleButtonClasses.banner)}
|
||||||
|
>
|
||||||
|
<NotesIcon height={16} width={16} />
|
||||||
|
</Button>
|
||||||
|
</TooltipContainer>
|
||||||
|
);
|
||||||
|
}, { noop: true })
|
||||||
});
|
});
|
||||||
|
|
|
@ -211,7 +211,7 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
find: ".BITE_SIZE,onOpenProfile",
|
find: /\.BITE_SIZE,onOpenProfile:\i,usernameIcon:/,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /currentUser:\i,guild:\i,onOpenProfile:.+?}\)(?=])(?<=user:(\i),bio:null==(\i)\?.+?)/,
|
match: /currentUser:\i,guild:\i,onOpenProfile:.+?}\)(?=])(?<=user:(\i),bio:null==(\i)\?.+?)/,
|
||||||
replace: "$&,$self.profilePopoutComponent({ user: $1, displayProfile: $2, simplified: true })"
|
replace: "$&,$self.profilePopoutComponent({ user: $1, displayProfile: $2, simplified: true })"
|
||||||
|
|
|
@ -105,6 +105,15 @@ export default definePlugin({
|
||||||
replace: "=[]"
|
replace: "=[]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// empty 2nd word filter
|
||||||
|
{
|
||||||
|
find: '"pepe","nude"',
|
||||||
|
predicate: () => settings.store.disableDisallowedDiscoveryFilters,
|
||||||
|
replacement: {
|
||||||
|
match: /\?\["pepe",.+?\]/,
|
||||||
|
replace: "?[]",
|
||||||
|
},
|
||||||
|
},
|
||||||
// patch request that queries if term is allowed
|
// patch request that queries if term is allowed
|
||||||
{
|
{
|
||||||
find: ".GUILD_DISCOVERY_VALID_TERM",
|
find: ".GUILD_DISCOVERY_VALID_TERM",
|
||||||
|
|
|
@ -66,12 +66,16 @@ export default definePlugin({
|
||||||
|
|
||||||
const { nick } = author;
|
const { nick } = author;
|
||||||
const prefix = withMentionPrefix ? "@" : "";
|
const prefix = withMentionPrefix ? "@" : "";
|
||||||
if (username === nick || isRepliedMessage && !settings.store.inReplies)
|
|
||||||
|
if (isRepliedMessage && !settings.store.inReplies || username === nick.toLowerCase())
|
||||||
return <>{prefix}{nick}</>;
|
return <>{prefix}{nick}</>;
|
||||||
|
|
||||||
if (settings.store.mode === "user-nick")
|
if (settings.store.mode === "user-nick")
|
||||||
return <>{prefix}{username} <span className="vc-smyn-suffix">{nick}</span></>;
|
return <>{prefix}{username} <span className="vc-smyn-suffix">{nick}</span></>;
|
||||||
|
|
||||||
if (settings.store.mode === "nick-user")
|
if (settings.store.mode === "nick-user")
|
||||||
return <>{prefix}{nick} <span className="vc-smyn-suffix">{username}</span></>;
|
return <>{prefix}{nick} <span className="vc-smyn-suffix">{username}</span></>;
|
||||||
|
|
||||||
return <>{prefix}{username}</>;
|
return <>{prefix}{username}</>;
|
||||||
} catch {
|
} catch {
|
||||||
return <>{author?.nick}</>;
|
return <>{author?.nick}</>;
|
||||||
|
|
|
@ -33,6 +33,7 @@ export let Card: t.Card;
|
||||||
export let Button: t.Button;
|
export let Button: t.Button;
|
||||||
export let Switch: t.Switch;
|
export let Switch: t.Switch;
|
||||||
export let Tooltip: t.Tooltip;
|
export let Tooltip: t.Tooltip;
|
||||||
|
export let TooltipContainer: t.TooltipContainer;
|
||||||
export let TextInput: t.TextInput;
|
export let TextInput: t.TextInput;
|
||||||
export let TextArea: t.TextArea;
|
export let TextArea: t.TextArea;
|
||||||
export let Text: t.Text;
|
export let Text: t.Text;
|
||||||
|
@ -66,6 +67,7 @@ waitFor(["FormItem", "Button"], m => {
|
||||||
Button,
|
Button,
|
||||||
FormSwitch: Switch,
|
FormSwitch: Switch,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
TooltipContainer,
|
||||||
TextInput,
|
TextInput,
|
||||||
TextArea,
|
TextArea,
|
||||||
Text,
|
Text,
|
||||||
|
|
44
src/webpack/common/types/components.d.ts
vendored
44
src/webpack/common/types/components.d.ts
vendored
|
@ -101,6 +101,28 @@ export type Tooltip = ComponentType<{
|
||||||
|
|
||||||
export type TooltipPositions = Record<"BOTTOM" | "CENTER" | "LEFT" | "RIGHT" | "TOP" | "WINDOW_CENTER", string>;
|
export type TooltipPositions = Record<"BOTTOM" | "CENTER" | "LEFT" | "RIGHT" | "TOP" | "WINDOW_CENTER", string>;
|
||||||
|
|
||||||
|
export type TooltipContainer = ComponentType<PropsWithChildren<{
|
||||||
|
text: ReactNode;
|
||||||
|
element?: "div" | "span";
|
||||||
|
"aria-label"?: string | false;
|
||||||
|
|
||||||
|
delay?: number;
|
||||||
|
/** Tooltip.Colors.BLACK */
|
||||||
|
color?: string;
|
||||||
|
/** TooltipPositions.TOP */
|
||||||
|
position?: string;
|
||||||
|
spacing?: number;
|
||||||
|
|
||||||
|
className?: string;
|
||||||
|
tooltipClassName?: string | null;
|
||||||
|
tooltipContentClassName?: string | null;
|
||||||
|
|
||||||
|
allowOverflow?: boolean;
|
||||||
|
forceOpen?: boolean;
|
||||||
|
hideOnClick?: boolean;
|
||||||
|
disableTooltipPointerEvents?: boolean;
|
||||||
|
}>>;
|
||||||
|
|
||||||
export type Card = ComponentType<PropsWithChildren<HTMLProps<HTMLDivElement> & {
|
export type Card = ComponentType<PropsWithChildren<HTMLProps<HTMLDivElement> & {
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
outline?: boolean;
|
outline?: boolean;
|
||||||
|
@ -110,6 +132,26 @@ export type Card = ComponentType<PropsWithChildren<HTMLProps<HTMLDivElement> & {
|
||||||
Types: Record<"BRAND" | "CUSTOM" | "DANGER" | "PRIMARY" | "SUCCESS" | "WARNING", string>;
|
Types: Record<"BRAND" | "CUSTOM" | "DANGER" | "PRIMARY" | "SUCCESS" | "WARNING", string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ComboboxPopout = ComponentType<PropsWithChildren<{
|
||||||
|
value: Set<any>;
|
||||||
|
placeholder: string;
|
||||||
|
children(query: string): ReactNode[];
|
||||||
|
|
||||||
|
onChange(value: any): void;
|
||||||
|
itemToString?: (item: any) => string;
|
||||||
|
onClose?(): void;
|
||||||
|
|
||||||
|
className?: string;
|
||||||
|
listClassName?: string;
|
||||||
|
|
||||||
|
|
||||||
|
autoFocus?: boolean;
|
||||||
|
multiSelect?: boolean;
|
||||||
|
maxVisibleItems?: number;
|
||||||
|
showScrollbar?: boolean;
|
||||||
|
|
||||||
|
}>>;
|
||||||
|
|
||||||
export type Button = ComponentType<PropsWithChildren<Omit<HTMLProps<HTMLButtonElement>, "size"> & {
|
export type Button = ComponentType<PropsWithChildren<Omit<HTMLProps<HTMLButtonElement>, "size"> & {
|
||||||
/** Button.Looks.FILLED */
|
/** Button.Looks.FILLED */
|
||||||
look?: string;
|
look?: string;
|
||||||
|
@ -375,7 +417,7 @@ export type Popout = ComponentType<{
|
||||||
Animation: typeof PopoutAnimation;
|
Animation: typeof PopoutAnimation;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Dialog = ComponentType<PropsWithChildren<any>>;
|
export type Dialog = ComponentType<JSX.IntrinsicElements["div"]>;
|
||||||
|
|
||||||
type Resolve = (data: { theme: "light" | "dark", saturation: number; }) => {
|
type Resolve = (data: { theme: "light" | "dark", saturation: number; }) => {
|
||||||
hex(): string;
|
hex(): string;
|
||||||
|
|
Loading…
Reference in a new issue