. #2
1 changed files with 28 additions and 14 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { findByProps, findByName } from "@vendetta/metro";
|
import { findByProps, findByName, findByTypeName } from "@vendetta/metro";
|
||||||
import { React } from "@vendetta/metro/common";
|
import { React } from "@vendetta/metro/common";
|
||||||
import { storage } from "@vendetta/plugin";
|
import { storage } from "@vendetta/plugin";
|
||||||
import { getAssetIDByName } from "@vendetta/ui/assets";
|
import { getAssetIDByName } from "@vendetta/ui/assets";
|
||||||
|
|
@ -9,12 +9,6 @@ import NotificationCenter from "../ui/NotificationCenter";
|
||||||
// this function itself simple.
|
// this function itself simple.
|
||||||
export let updateYouBar = () => {};
|
export let updateYouBar = () => {};
|
||||||
|
|
||||||
// findByTypeName + instead("type", ...) used to patch this, but that mutates whatever object
|
|
||||||
// Metro's search hands back - which isn't reliably the same reference Discord's own render call
|
|
||||||
// site reads from in this bundle (confirmed live: the property write didn't stick, and a fresh
|
|
||||||
// findByTypeName call moments later returned undefined). registerTypeDetector instead captures
|
|
||||||
// the exact type value at the actual createElement/jsx call site, so there's no reference
|
|
||||||
// mismatch to go stale.
|
|
||||||
export default function patchYouBarButtons(): () => void {
|
export default function patchYouBarButtons(): () => void {
|
||||||
const userSettingsAction = findByProps("openUserSettings");
|
const userSettingsAction = findByProps("openUserSettings");
|
||||||
const transitionModule = findByProps("transitionToGuild");
|
const transitionModule = findByProps("transitionToGuild");
|
||||||
|
|
@ -27,6 +21,9 @@ export default function patchYouBarButtons(): () => void {
|
||||||
|
|
||||||
const SettingsIcon = getAssetIDByName("SettingsIcon");
|
const SettingsIcon = getAssetIDByName("SettingsIcon");
|
||||||
const ChatIcon = getAssetIDByName("ChatIcon");
|
const ChatIcon = getAssetIDByName("ChatIcon");
|
||||||
|
const BellIcon = getAssetIDByName("BellIcon") || getAssetIDByName("NotificationBellIcon");
|
||||||
|
|
||||||
|
const TargetNotificationsButton = findByTypeName("YouBarNotificationsButton");
|
||||||
|
|
||||||
const openInbox = () => {
|
const openInbox = () => {
|
||||||
if (!Navigator || !Navigation?.push) {
|
if (!Navigator || !Navigation?.push) {
|
||||||
|
|
@ -51,17 +48,34 @@ export default function patchYouBarButtons(): () => void {
|
||||||
const cleanups: (() => void)[] = [];
|
const cleanups: (() => void)[] = [];
|
||||||
|
|
|||||||
patchCreateElement(cleanups);
|
patchCreateElement(cleanups);
|
||||||
|
|
||||||
// The native bell is one of four sibling buttons YouBarNotificationsButton renders - the
|
// Matches the notification button reliably even if Discord localizes or changes accessibilityLabel,
|
||||||
// other three are unrelated icon buttons with raw numeric asset ids. accessibilityLabel is
|
// safely guarding BellIcon so undefined doesn't match iconless props.
|
||||||
// the only reliable way to pick the real bell out (confirmed live via the fiber tree).
|
|
||||||
registerPropsTransform(
|
registerPropsTransform(
|
||||||
(props) => !!storage.showInboxButton && props?.accessibilityLabel === "Notifications",
|
(props) => {
|
||||||
(props) => ({ ...props, onPress: openInbox }),
|
if (!storage.showInboxButton) return false;
|
||||||
|
const label = props?.accessibilityLabel?.toLowerCase();
|
||||||
|
return (
|
||||||
|
label === "notifications" ||
|
||||||
|
label === "inbox" ||
|
||||||
|
(BellIcon != null && props?.icon === BellIcon)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(props) => ({
|
||||||
|
...props,
|
||||||
|
onPress: openInbox,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
registerTypeDetector(
|
registerTypeDetector(
|
||||||
"you-bar-plus-notifications-button",
|
"you-bar-plus-notifications-button",
|
||||||
(type) => typeof type === "function" && type.name === "YouBarNotificationsButton",
|
(type) => {
|
||||||
|
// Check direct Metro resolution first to bypass production Hermes type.name mangling
|
||||||
|
if (TargetNotificationsButton && type === TargetNotificationsButton) return true;
|
||||||
|
return typeof type === "function" && (
|
||||||
|
type.name === "YouBarNotificationsButton" ||
|
||||||
|
type.displayName === "YouBarNotificationsButton"
|
||||||
|
);
|
||||||
|
},
|
||||||
(YouBarNotificationsButton: any) => {
|
(YouBarNotificationsButton: any) => {
|
||||||
const PatchedYouBarNotificationsButton = (props: any) => {
|
const PatchedYouBarNotificationsButton = (props: any) => {
|
||||||
const [, forceUpdate] = React.useReducer((x: number) => ~x, 0);
|
const [, forceUpdate] = React.useReducer((x: number) => ~x, 0);
|
||||||
|
|
@ -98,7 +112,7 @@ export default function patchYouBarButtons(): () => void {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{res}
|
{storage.showInboxButton !== false && res}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Guard the unresolved Bell icon before comparing it.
If both
getAssetIDByNamecalls returnundefined,BellIconisundefined. Thenprops?.icon === BellIconmatches every props object without an icon. The transform can replace unrelatedonPresshandlers withopenInbox. Require a resolved icon before the equality check.Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents