CopyRoleColor: copy gradient roles as JSON, not just the flattened hex
This commit is contained in:
parent
3e72269c10
commit
19cfaac538
1 changed files with 28 additions and 7 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { logger } from "@vendetta";
|
||||
import { findByName } from "@vendetta/metro";
|
||||
import { findByName, findByStoreName } from "@vendetta/metro";
|
||||
import { after } from "@vendetta/patcher";
|
||||
import { findInReactTree } from "@vendetta/utils";
|
||||
import { clipboard } from "@vendetta/metro/common";
|
||||
|
|
@ -8,6 +8,17 @@ import { showToast } from "@vendetta/ui/toasts";
|
|||
import { applyPatches } from "@shared/lib/patcher";
|
||||
import { registerTypeDetector, registerIntercept, patchCreateElement } from "@shared/lib/createElementIntercept";
|
||||
|
||||
// A gradient role's real colors live at role.colorStrings ({primaryColor, secondaryColor,
|
||||
// tertiaryColor}), not the flattened colorString - copying that exact JSON back into Discord's own
|
||||
// role color picker recreates the gradient. A solid-color role only has primaryColor set, so this
|
||||
// falls back to the plain hex for those, keeping the existing single-color behavior unchanged.
|
||||
function getClipboardValue(colorStrings: any, fallbackColor?: string | null): string | null {
|
||||
if (colorStrings?.primaryColor && colorStrings?.secondaryColor) {
|
||||
return JSON.stringify(colorStrings);
|
||||
}
|
||||
return colorStrings?.primaryColor ?? fallbackColor ?? null;
|
||||
}
|
||||
|
||||
function patchRolePill(): () => void {
|
||||
// Confirmed against decompiled current-build Discord source: the component is now just
|
||||
// "RolePill" (at app/components_native/common/RolePill.tsx) - "ThemedRolePill" doesn't exist
|
||||
|
|
@ -15,6 +26,8 @@ function patchRolePill(): () => void {
|
|||
const RolePillComponent = findByName("RolePill", false) ?? findByName("ThemedRolePill", false);
|
||||
if (!RolePillComponent) return () => {};
|
||||
|
||||
const GuildRoleStore = findByStoreName("GuildRoleStore");
|
||||
|
||||
return after("default", RolePillComponent, (_args: any[], res: any) => {
|
||||
try {
|
||||
if (!res?.props?.onPress) return;
|
||||
|
|
@ -27,8 +40,16 @@ function patchRolePill(): () => void {
|
|||
const color = roleIcon?.props?.style?.[1]?.backgroundColor ?? verifiedIcon?.props?.roleColor;
|
||||
if (!color) return;
|
||||
|
||||
// The pill only gives us a flattened color from its rendered style - fetching the real
|
||||
// role record (if guildId/roleId are present on it) is what actually exposes the gradient.
|
||||
const guildId = res.props?.guildId;
|
||||
const roleId = res.props?.roleId ?? res.props?.role?.id;
|
||||
const role = guildId && roleId ? GuildRoleStore?.getRole?.(guildId, roleId) : null;
|
||||
const value = getClipboardValue(role?.colorStrings, color);
|
||||
if (!value) return;
|
||||
|
||||
res.props.onLongPress = () => {
|
||||
clipboard.setString(color);
|
||||
clipboard.setString(value);
|
||||
showToast("Copied role color to clipboard", getAssetIDByName("ic_message_copy"));
|
||||
};
|
||||
} catch {
|
||||
|
|
@ -40,8 +61,8 @@ function patchRolePill(): () => void {
|
|||
// Covers the role pills in a full profile's Roles section - a different render path from
|
||||
// patchRolePill above (that one's for role mentions in message text). This section renders
|
||||
// UserProfileRolesCard -> RolesList -> RoleItem, none of which are top-level exports, so we need
|
||||
// createElementIntercept to catch RoleItem's reference. It hands us the role object directly with
|
||||
// role.colorString already a hex string, so no need to guess at it from rendered styles.
|
||||
// createElementIntercept to catch RoleItem's reference. It hands us the role object directly, with
|
||||
// both colorStrings and colorString on it already, so no need to guess at it from rendered styles.
|
||||
function patchProfileRoleItem(): () => void {
|
||||
const cleanups: (() => void)[] = [];
|
||||
patchCreateElement(cleanups);
|
||||
|
|
@ -54,12 +75,12 @@ function patchProfileRoleItem(): () => void {
|
|||
const ret = RoleItem(props);
|
||||
|
||||
try {
|
||||
const color = props?.role?.colorString;
|
||||
if (color && ret && typeof ret === "object") {
|
||||
const value = getClipboardValue(props?.role?.colorStrings, props?.role?.colorString);
|
||||
if (value && ret && typeof ret === "object") {
|
||||
ret.props = {
|
||||
...ret.props,
|
||||
onLongPress: () => {
|
||||
clipboard.setString(color);
|
||||
clipboard.setString(value);
|
||||
showToast("Copied role color to clipboard", getAssetIDByName("ic_message_copy"));
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue