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 patchChat from "./patches/chat";
|
||||||
import patchName from "./patches/name";
|
import patchName from "./patches/name";
|
||||||
import patchDetails from "./patches/details";
|
import patchDetails from "./patches/details";
|
||||||
|
import patchProfile from "./patches/profile";
|
||||||
import patchTag from "./patches/tag";
|
import patchTag from "./patches/tag";
|
||||||
import Settings from "./ui/Settings";
|
import Settings from "./ui/Settings";
|
||||||
|
|
||||||
|
|
@ -17,7 +18,8 @@ export default {
|
||||||
tag: patchTag,
|
tag: patchTag,
|
||||||
chat: patchChat,
|
chat: patchChat,
|
||||||
name: patchName,
|
name: patchName,
|
||||||
details: patchDetails
|
details: patchDetails,
|
||||||
|
profile: patchProfile
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onUnload: () => unpatchAll(),
|
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 patchChat from "./patches/chat";
|
||||||
import patchDetails from "./patches/details";
|
import patchDetails from "./patches/details";
|
||||||
import patchName from "./patches/name";
|
import patchName from "./patches/name";
|
||||||
|
import patchProfile from "./patches/profile";
|
||||||
import patchTag from "./patches/tag";
|
import patchTag from "./patches/tag";
|
||||||
import Settings from "./ui/pages/Settings";
|
import Settings from "./ui/pages/Settings";
|
||||||
|
|
||||||
|
|
@ -18,7 +19,8 @@ export default {
|
||||||
tag: patchTag,
|
tag: patchTag,
|
||||||
chat: patchChat,
|
chat: patchChat,
|
||||||
name: patchName,
|
name: patchName,
|
||||||
details: patchDetails
|
details: patchDetails,
|
||||||
|
profile: patchProfile
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onUnload: () => unpatchAll(),
|
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