Staff Tags/Custom User Tags: show tags on the full profile screen too
This commit is contained in:
parent
2b111e7d8c
commit
66d1777e44
4 changed files with 158 additions and 2 deletions
|
|
@ -4,6 +4,7 @@ import { applyPatches } from "@shared/lib/patcher";
|
|||
import patchChat from "./patches/chat";
|
||||
import patchName from "./patches/name";
|
||||
import patchDetails from "./patches/details";
|
||||
import patchProfile from "./patches/profile";
|
||||
import patchTag from "./patches/tag";
|
||||
import Settings from "./ui/Settings";
|
||||
|
||||
|
|
@ -17,7 +18,8 @@ export default {
|
|||
tag: patchTag,
|
||||
chat: patchChat,
|
||||
name: patchName,
|
||||
details: patchDetails
|
||||
details: patchDetails,
|
||||
profile: patchProfile
|
||||
});
|
||||
},
|
||||
onUnload: () => unpatchAll(),
|
||||
|
|
|
|||
70
plugins/custom-user-tags/src/patches/profile.tsx
Normal file
70
plugins/custom-user-tags/src/patches/profile.tsx
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { find, findByProps } from "@vendetta/metro";
|
||||
import { after } from "@vendetta/patcher";
|
||||
import { findInReactTree } from "@vendetta/utils";
|
||||
import resolveTag from "../lib/resolveTag";
|
||||
|
||||
// Same top-level profile component PronounDB already confirmed works, and the same one Staff Tags
|
||||
// now patches for its own profile-screen tag - see that plugin's patches/profile.tsx for the full
|
||||
// writeup on why this is a separate component from UserRow (which details.tsx already handles).
|
||||
const UserProfile =
|
||||
find((m: any) => m?.type?.name === "UserProfileContent") ??
|
||||
find((m: any) => m?.type?.name === "UserProfile");
|
||||
|
||||
const TagModule = findByProps("getBotLabel");
|
||||
|
||||
/**
|
||||
* Not independently confirmed against a live render yet - the exact prop shape passed to this
|
||||
* component isn't verified on-device, so this pulls from whichever of several plausible field names
|
||||
* is actually present. Every step is guarded, so a wrong assumption just means no tag appears here.
|
||||
*/
|
||||
export default function patchProfile(): () => void {
|
||||
if (!UserProfile) return () => {};
|
||||
|
||||
return after("type", UserProfile, (args: any[], res: any) => {
|
||||
try {
|
||||
const props = args?.[0] ?? {};
|
||||
const userId: string | undefined = props.userId ?? props.user?.id ?? props.displayProfile?.userId;
|
||||
if (!userId) return;
|
||||
|
||||
const tag = resolveTag(userId);
|
||||
if (!tag) return;
|
||||
|
||||
const primaryInfo = findInReactTree(res, (c) => c?.type?.name === "PrimaryInfo" || c?.type?.displayName === "PrimaryInfo");
|
||||
if (!primaryInfo) return;
|
||||
|
||||
const existingTag = findInReactTree(primaryInfo, (c) => c?.type?.Types);
|
||||
if (existingTag && existingTag.props?.type !== 0) return;
|
||||
|
||||
if (existingTag) {
|
||||
Object.assign(existingTag.props, {
|
||||
type: 0,
|
||||
text: tag.text,
|
||||
textColor: tag.textColor,
|
||||
backgroundColor: tag.backgroundColor,
|
||||
verified: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const nameRow = findInReactTree(
|
||||
primaryInfo,
|
||||
(c) =>
|
||||
Array.isArray(c?.props?.children) &&
|
||||
c.props.children.some((ch: any) => typeof ch === "string" || typeof ch?.props?.children === "string")
|
||||
);
|
||||
if (!Array.isArray(nameRow?.props?.children) || !TagModule) return;
|
||||
|
||||
nameRow.props.children.push(
|
||||
<TagModule.default
|
||||
type={0}
|
||||
text={tag.text}
|
||||
textColor={tag.textColor}
|
||||
backgroundColor={tag.backgroundColor}
|
||||
verified={false}
|
||||
/>
|
||||
);
|
||||
} catch {
|
||||
// Skip - a broken profile tag beats a crashed profile screen.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import { applyPatches } from "@shared/lib/patcher";
|
|||
import patchChat from "./patches/chat";
|
||||
import patchDetails from "./patches/details";
|
||||
import patchName from "./patches/name";
|
||||
import patchProfile from "./patches/profile";
|
||||
import patchTag from "./patches/tag";
|
||||
import Settings from "./ui/pages/Settings";
|
||||
|
||||
|
|
@ -18,7 +19,8 @@ export default {
|
|||
tag: patchTag,
|
||||
chat: patchChat,
|
||||
name: patchName,
|
||||
details: patchDetails
|
||||
details: patchDetails,
|
||||
profile: patchProfile
|
||||
});
|
||||
},
|
||||
onUnload: () => unpatchAll(),
|
||||
|
|
|
|||
82
plugins/staff-tags/src/patches/profile.tsx
Normal file
82
plugins/staff-tags/src/patches/profile.tsx
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { find, findByProps, findByStoreName } from "@vendetta/metro";
|
||||
import { after } from "@vendetta/patcher";
|
||||
import { findInReactTree } from "@vendetta/utils";
|
||||
import getTag from "../lib/getTag";
|
||||
|
||||
// Same top-level profile component PronounDB already confirmed works on current Discord (the
|
||||
// findByName-based lookup this repo used to use for it stopped matching after a rename, but this
|
||||
// predicate-based find still succeeds). The full profile screen doesn't render through UserRow the
|
||||
// way member list rows and the old "profile popout" did - this is a separate component entirely,
|
||||
// which is why tags weren't showing up here even though details.tsx's own patch is working fine.
|
||||
const UserProfile =
|
||||
find((m: any) => m?.type?.name === "UserProfileContent") ??
|
||||
find((m: any) => m?.type?.name === "UserProfile");
|
||||
|
||||
const TagModule = findByProps("getBotLabel");
|
||||
const GuildStore = findByStoreName("GuildStore");
|
||||
const UserStore = findByStoreName("UserStore");
|
||||
|
||||
/**
|
||||
* Not independently confirmed against a live render the way most of this repo's fixes are - the
|
||||
* exact prop shape passed to this component's render (userId vs. a full user object, whether
|
||||
* guildId is even present) isn't verified on-device yet, so this pulls from whichever of several
|
||||
* plausible field names is actually present rather than assuming one. Every step is guarded, so a
|
||||
* wrong assumption just means no tag appears here, not a crash.
|
||||
*/
|
||||
export default function patchProfile(): () => void {
|
||||
if (!UserProfile) return () => {};
|
||||
|
||||
return after("type", UserProfile, (args: any[], res: any) => {
|
||||
try {
|
||||
const props = args?.[0] ?? {};
|
||||
const userId: string | undefined = props.userId ?? props.user?.id ?? props.displayProfile?.userId;
|
||||
if (!userId) return;
|
||||
|
||||
const user = props.user ?? UserStore?.getUser?.(userId);
|
||||
if (!user) return;
|
||||
|
||||
const guildId: string | undefined = props.guildId;
|
||||
const guild = guildId ? GuildStore?.getGuild(guildId) : undefined;
|
||||
|
||||
const tag = getTag(guild, undefined, user);
|
||||
if (!tag) return;
|
||||
|
||||
const primaryInfo = findInReactTree(res, (c) => c?.type?.name === "PrimaryInfo" || c?.type?.displayName === "PrimaryInfo");
|
||||
if (!primaryInfo) return;
|
||||
|
||||
const existingTag = findInReactTree(primaryInfo, (c) => c?.type?.Types);
|
||||
if (existingTag && existingTag.props?.type !== 0) return;
|
||||
|
||||
if (existingTag) {
|
||||
Object.assign(existingTag.props, {
|
||||
type: 0,
|
||||
text: tag.text,
|
||||
textColor: tag.textColor,
|
||||
backgroundColor: tag.backgroundColor,
|
||||
verified: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const nameRow = findInReactTree(
|
||||
primaryInfo,
|
||||
(c) =>
|
||||
Array.isArray(c?.props?.children) &&
|
||||
c.props.children.some((ch: any) => typeof ch === "string" || typeof ch?.props?.children === "string")
|
||||
);
|
||||
if (!Array.isArray(nameRow?.props?.children) || !TagModule) return;
|
||||
|
||||
nameRow.props.children.push(
|
||||
<TagModule.default
|
||||
type={0}
|
||||
text={tag.text}
|
||||
textColor={tag.textColor}
|
||||
backgroundColor={tag.backgroundColor}
|
||||
verified={false}
|
||||
/>
|
||||
);
|
||||
} catch {
|
||||
// Skip - a broken profile tag beats a crashed profile screen.
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue