diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts
index ab881e60c..221b115f6 100644
--- a/src/plugins/crashHandler/index.ts
+++ b/src/plugins/crashHandler/index.ts
@@ -175,7 +175,7 @@ export default definePlugin({
}
if (settings.store.attemptToNavigateToHome) {
try {
- NavigationRouter.transitionTo("/channels/@me");
+ NavigationRouter.transitionToGuild("@me");
} catch (err) {
CrashHandlerLogger.debug("Failed to navigate to home", err);
}
diff --git a/src/plugins/keepCurrentChannel/index.ts b/src/plugins/keepCurrentChannel/index.ts
index b226c34e3..1e0e742dc 100644
--- a/src/plugins/keepCurrentChannel/index.ts
+++ b/src/plugins/keepCurrentChannel/index.ts
@@ -19,7 +19,7 @@
import * as DataStore from "@api/DataStore";
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
-import { ChannelStore, NavigationRouter, SelectedChannelStore, SelectedGuildStore } from "@webpack/common";
+import { ChannelRouter, SelectedChannelStore, SelectedGuildStore } from "@webpack/common";
export interface LogoutEvent {
type: "LOGOUT";
@@ -40,11 +40,6 @@ interface PreviousChannel {
let isSwitchingAccount = false;
let previousCache: PreviousChannel | undefined;
-function attemptToNavigateToChannel(guildId: string | null, channelId: string) {
- if (!ChannelStore.hasChannel(channelId)) return;
- NavigationRouter.transitionTo(`/channels/${guildId ?? "@me"}/${channelId}`);
-}
-
export default definePlugin({
name: "KeepCurrentChannel",
description: "Attempt to navigate to the channel you were in before switching accounts or loading Discord.",
@@ -59,8 +54,9 @@ export default definePlugin({
if (!isSwitchingAccount) return;
isSwitchingAccount = false;
- if (previousCache?.channelId)
- attemptToNavigateToChannel(previousCache.guildId, previousCache.channelId);
+ if (previousCache?.channelId) {
+ ChannelRouter.transitionToChannel(previousCache.channelId);
+ }
},
async CHANNEL_SELECT({ guildId, channelId }: ChannelSelectEvent) {
@@ -84,7 +80,7 @@ export default definePlugin({
await DataStore.set("KeepCurrentChannel_previousData", previousCache);
} else if (previousCache.channelId) {
- attemptToNavigateToChannel(previousCache.guildId, previousCache.channelId);
+ ChannelRouter.transitionToChannel(previousCache.channelId);
}
}
});
diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx
index fad860dfa..f9a81c4b9 100644
--- a/src/plugins/userVoiceShow/components.tsx
+++ b/src/plugins/userVoiceShow/components.tsx
@@ -8,7 +8,7 @@ import { classNameFactory } from "@api/Styles";
import ErrorBoundary from "@components/ErrorBoundary";
import { classes } from "@utils/misc";
import { filters, findByCodeLazy, findByPropsLazy, findComponentByCodeLazy, findStoreLazy, mapMangledModuleLazy } from "@webpack";
-import { ChannelStore, GuildStore, IconUtils, match, NavigationRouter, P, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common";
+import { ChannelRouter, ChannelStore, GuildStore, IconUtils, match, P, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common";
import { Channel } from "discord-types/general";
const cl = classNameFactory("vc-uvs-");
@@ -24,6 +24,8 @@ const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaul
const Avatar = findComponentByCodeLazy(".AVATAR_STATUS_TYPING_16;");
const GroupDMAvatars = findComponentByCodeLazy(".AvatarSizeSpecs[", "getAvatarURL");
+const ActionButtonClasses = findByPropsLazy("actionButton", "highlight");
+
interface IconProps extends React.ComponentPropsWithoutRef<"div"> {
size?: number;
}
@@ -74,9 +76,10 @@ function LockedSpeakerIcon(props: IconProps) {
interface VoiceChannelTooltipProps {
channel: Channel;
+ isLocked: boolean;
}
-function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) {
+function VoiceChannelTooltip({ channel, isLocked }: VoiceChannelTooltipProps) {
const voiceStates = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStatesForChannel(channel.id));
const users = useMemo(
@@ -113,7 +116,7 @@ function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) {
{channelName}
-
+ {isLocked ? : }
;
-export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActionButton }: VoiceChannelIndicatorProps) => {
+export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndicator, isProfile, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => {
const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined);
const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId);
@@ -165,7 +170,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActio
selectVoiceChannel(channelId);
} else {
clickTimers[channelId] = setTimeout(() => {
- NavigationRouter.transitionTo(`/channels/${channel.getGuildId() ?? "@me"}/${channelId}`);
+ ChannelRouter.transitionToChannel(channelId);
delete clickTimers[channelId];
}, 250);
}
@@ -173,16 +178,16 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActio
return (
}
+ text={}
tooltipClassName={cl("tooltip-container")}
tooltipContentClassName={cl("tooltip-content")}
>
{props => {
- const iconProps = {
+ const iconProps: IconProps = {
...props,
- onClick,
- size,
- className: isActionButton ? cl("indicator-action-button") : cl("speaker-padding")
+ className: classes(isMessageIndicator && cl("message-indicator"), (!isProfile && !isActionButton) && cl("speaker-margin"), isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight),
+ size: isActionButton ? 20 : undefined,
+ onClick
};
return isLocked ?
diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx
index 573fd0e38..98386a16e 100644
--- a/src/plugins/userVoiceShow/index.tsx
+++ b/src/plugins/userVoiceShow/index.tsx
@@ -19,6 +19,7 @@
import "./style.css";
import { addDecorator, removeDecorator } from "@api/MemberListDecorators";
+import { addDecoration, removeDecoration } from "@api/MessageDecorations";
import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
@@ -37,13 +38,19 @@ const settings = definePluginSettings({
description: "Show a user's Voice Channel indicator in the member and DMs list",
default: true,
restartNeeded: true
+ },
+ showInMessages: {
+ type: OptionType.BOOLEAN,
+ description: "Show a user's Voice Channel indicator in messages",
+ default: true,
+ restartNeeded: true
}
});
export default definePlugin({
name: "UserVoiceShow",
description: "Shows an indicator when a user is in a Voice Channel",
- authors: [Devs.LordElias, Devs.Nuckyz],
+ authors: [Devs.Nuckyz, Devs.LordElias],
settings,
patches: [
@@ -52,7 +59,7 @@ export default definePlugin({
find: ".Messages.USER_PROFILE_LOAD_ERROR",
replacement: {
match: /(\.fetchError.+?\?)null/,
- replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId})`
+ replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId,isProfile:true})`
},
predicate: () => settings.store.showInUserProfileModal
},
@@ -79,8 +86,8 @@ export default definePlugin({
{
find: "null!=this.peopleListItemRef.current",
replacement: {
- match: /\.actions,children:\[/,
- replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,size:20,isActionButton:true}),"
+ match: /\.actions,children:\[(?<=isFocused:(\i).+?)/,
+ replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,isActionButton:true,shouldHighlight:$1}),"
},
predicate: () => settings.store.showInMemberList
}
@@ -90,10 +97,14 @@ export default definePlugin({
if (settings.store.showInMemberList) {
addDecorator("UserVoiceShow", ({ user }) => user == null ? null : );
}
+ if (settings.store.showInMessages) {
+ addDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : );
+ }
},
stop() {
removeDecorator("UserVoiceShow");
+ removeDecoration("UserVoiceShow");
},
VoiceChannelIndicator
diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css
index 67f4c4958..d172975b8 100644
--- a/src/plugins/userVoiceShow/style.css
+++ b/src/plugins/userVoiceShow/style.css
@@ -13,16 +13,14 @@
color: var(--interactive-hover);
}
-.vc-uvs-speaker-padding {
- padding: 0 4px;
+.vc-uvs-speaker-margin {
+ margin-left: 4px;
}
-.vc-uvs-indicator-action-button {
- background-color: var(--background-secondary);
- border-radius: 100%;
- height: 36px;
- width: 36px;
- margin-left: 10px;
+.vc-uvs-message-indicator {
+ display: inline-flex;
+ top: 2.5px;
+ position: relative;
}
.vc-uvs-tooltip-container {
diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts
index dd76d1ade..c0a930049 100644
--- a/src/webpack/common/types/utils.d.ts
+++ b/src/webpack/common/types/utils.d.ts
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-import { Guild, GuildMember, User } from "discord-types/general";
+import { Channel, Guild, GuildMember, User } from "discord-types/general";
import type { ReactNode } from "react";
import { LiteralUnion } from "type-fest";
@@ -173,6 +173,11 @@ export interface NavigationRouter {
transitionToGuild(guildId: string, ...args: unknown[]): void;
}
+export interface ChannelRouter {
+ transitionToChannel: (channelId: string) => void;
+ transitionToThread: (channel: Channel) => void;
+}
+
export interface IconUtils {
getUserAvatarURL(user: User, canAnimate?: boolean, size?: number, format?: string): string;
getDefaultAvatarURL(id: string, discriminator?: string): string;
diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts
index b557f4da2..2d0026b58 100644
--- a/src/webpack/common/utils.ts
+++ b/src/webpack/common/utils.ts
@@ -149,6 +149,10 @@ export const NavigationRouter: t.NavigationRouter = mapMangledModuleLazy("Transi
back: filters.byCode("goBack()"),
forward: filters.byCode("goForward()"),
});
+export const ChannelRouter: t.ChannelRouter = mapMangledModuleLazy('"Thread must have a parent ID."', {
+ transitionToChannel: filters.byCode(".preload"),
+ transitionToThread: filters.byCode('"Thread must have a parent ID."')
+});
export let SettingsRouter: any;
waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m);