From 8e79b77f754e1179561c5d2078beda0a5d9c1107 Mon Sep 17 00:00:00 2001 From: everestmcarthur Date: Sun, 2 Aug 2026 18:11:23 +0000 Subject: [PATCH] deploy: 86c3708e870b7935bc281572c11364280b0d6eae --- key-inspector/install/index.js | 44 ++++++++++++++--------------- key-inspector/install/manifest.json | 2 +- server-drawer/install/index.js | 2 +- server-drawer/install/manifest.json | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/key-inspector/install/index.js b/key-inspector/install/index.js index 0b196cd..4931781 100644 --- a/key-inspector/install/index.js +++ b/key-inspector/install/index.js @@ -1,32 +1,32 @@ -(function(E,e,s,p,k,B,v,F){"use strict";const{ScrollView:A,View:j}=e.ReactNative;function _({children:t}){return e.React.createElement(A,{style:{flex:1}},t,e.React.createElement(j,{style:{height:24}}))}const{View:O,Text:I}=e.ReactNative;function D({children:t,style:a}){return e.React.createElement(O,{style:[{marginHorizontal:16,marginVertical:8,padding:10,borderRadius:8,borderWidth:1,borderColor:"rgba(128,128,128,0.25)"},a]},e.React.createElement(I,{style:{fontSize:12.5,lineHeight:18,opacity:.75}},t))}const{TouchableOpacity:z,Text:H}=e.ReactNative;function h({label:t,onPress:a,disabled:n,style:o}){return e.React.createElement(z,{disabled:n,onPress:a,style:[{backgroundColor:"#5865F2",borderRadius:8,padding:10,alignItems:"center",opacity:n?.5:1},o]},e.React.createElement(H,{style:{color:"white",fontWeight:"600"}},t))}function S(t){const a=window?.modules;if(a)for(const n in a){const o=a[n];if(!o?.isInitialized)continue;const r=o.publicModule?.exports;if(r)try{if(t(r))return r;if(r.default!=null&&t(r.default))return r.default}catch{}}}function T(t){return S(function(a){return a?.name===t||a?.displayName===t||a?.type?.name===t||a?.type?.displayName===t})}function m(t){return S(function(a){return a?.name===t||a?.displayName===t})}function P(...t){return S(function(a){return t.every(function(n){return a?.[n]!==void 0})})}function C(t){return S(function(a){return typeof a?.getName=="function"&&a.getName.length===0&&a.getName()===t})}const x=[{label:'findByProps("computePermissions", "canEveryoneRole")',run:function(){return s.findByProps("computePermissions","canEveryoneRole")}},{label:'findByProps("getBotLabel")',run:function(){return s.findByProps("getBotLabel")}},{label:'findByName("DisplayName", false)',run:function(){return s.findByName("DisplayName",!1)}},{label:'findByName("HeaderName", false)',run:function(){return s.findByName("HeaderName",!1)}},{label:'findByName("getTagProperties", false)',run:function(){return s.findByName("getTagProperties",!1)}},{label:'findByTypeNameAll("UserRow")',run:function(){return s.findByTypeNameAll("UserRow")}},{label:'findByStoreName("ThemeStore")',run:function(){return s.findByStoreName("ThemeStore")}},{label:'findByStoreName("GuildMemberStore")',run:function(){return s.findByStoreName("GuildMemberStore")}},{label:'findByStoreName("GuildStore")',run:function(){return s.findByStoreName("GuildStore")}},{label:'findByStoreName("ChannelStore")',run:function(){return s.findByStoreName("ChannelStore")}},{label:'findByStoreName("UserStore")',run:function(){return s.findByStoreName("UserStore")}},{label:'findByStoreName("RelationshipStore")',run:function(){return s.findByStoreName("RelationshipStore")}},{label:'findByName("RowManager", false)',run:function(){return s.findByName("RowManager",!1)}},{label:'findByProps("TYPING_WRAPPER_HEIGHT")',run:function(){return s.findByProps("TYPING_WRAPPER_HEIGHT")}},{label:'findByName("VoiceUserConnected", false)',run:function(){return s.findByName("VoiceUserConnected",!1)}},{label:"find(resolveSemanticColor via default.internal)",run:function(){return s.find(function(t){return t?.default?.internal?.resolveSemanticColor})}},{label:"find(resolveSemanticColor via meta)",run:function(){return s.find(function(t){return t?.meta?.resolveSemanticColor})}},{label:"find(UserProfile)",run:function(){return s.find(function(t){return t?.type?.name==="UserProfile"})}},{label:'findByName("UserProfileSection", false)',run:function(){return s.findByName("UserProfileSection",!1)}},{label:'findByProps("sendMessage", "sendBotMessage")',run:function(){return s.findByProps("sendMessage","sendBotMessage")}},{label:'findByProps("openLazy", "hideActionSheet")',run:function(){return s.findByProps("openLazy","hideActionSheet")}},{label:'findByProps("push", "pushLazy", "pop")',run:function(){return s.findByProps("push","pushLazy","pop")}},{label:'findByProps("getRenderCloseButton")',run:function(){return s.findByProps("getRenderCloseButton")}},{label:'findByProps("getHeaderCloseButton")',run:function(){return s.findByProps("getHeaderCloseButton")}},{label:'findByName("Navigator")',run:function(){return s.findByName("Navigator")}},{label:'findByName("ThemedRolePill", false)',run:function(){return s.findByName("ThemedRolePill",!1)}},{label:'findByProps("saveProfileChanges")',run:function(){return s.findByProps("saveProfileChanges")}},{label:'findByProps("useAvatarColors")',run:function(){return s.findByProps("useAvatarColors")}},{label:'findByProps("useThemeContext")',run:function(){return s.findByProps("useThemeContext")}},{label:'findByProps("getProfileTheme")',run:function(){return s.findByProps("getProfileTheme")}},{label:'findByProps("ThemeContextProvider")',run:function(){return s.findByProps("ThemeContextProvider")}},{label:"semanticColors.HEADER_SECONDARY",run:function(){return B.semanticColors?.HEADER_SECONDARY}},{label:"semanticColors.BACKGROUND_ACCENT",run:function(){return B.semanticColors?.BACKGROUND_ACCENT}},{label:"semanticColors.BACKGROUND_PRIMARY",run:function(){return B.semanticColors?.BACKGROUND_PRIMARY}},{label:"semanticColors.BACKGROUND_FLOATING",run:function(){return B.semanticColors?.BACKGROUND_FLOATING}},{label:"semanticColors.BUTTON_OUTLINE_BRAND_BORDER_ACTIVE",run:function(){return B.semanticColors?.BUTTON_OUTLINE_BRAND_BORDER_ACTIVE}},{label:"semanticColors.TEXT_NORMAL",run:function(){return B.semanticColors?.TEXT_NORMAL}}];function M(t){if(t==null)return"NOT FOUND";if(typeof t=="object"){const a=Object.keys(t);return`found (${a.length} key${a.length===1?"":"s"})`}return`found (${typeof t})`}function U(){return x.map(function({label:t,run:a}){try{const n=a();return{label:t,found:n!=null,detail:M(n)}}catch(n){return{label:t,found:!1,detail:`threw: ${n}`}}})}function V(t){const a=t.filter(function(n){return!n.found});return[`Key Inspector report - ${new Date().toISOString()}`,`${t.length} checked, ${a.length} missing`,"",...t.map(function(n){return`[${n.found?"OK":"MISSING"}] ${n.label} -> ${n.detail}`}),"",`semanticColors keys (${Object.keys(B.semanticColors??{}).length}):`,...Object.keys(B.semanticColors??{}).sort(),"",`rawColors keys (${Object.keys(B.rawColors??{}).length}):`,...Object.keys(B.rawColors??{}).sort()].join(` -`)}const G=new Set(["vendetta.metro.modules"]);function L(t){return t===null?"null":t===void 0?"undefined":Array.isArray(t)?`array(${t.length})`:typeof t}function W(t=3){const a=new WeakSet,n=[];function o(r,c,u){if(r==null||typeof r!="object"&&typeof r!="function")return;if(G.has(c)){n.push(`${c} -> (skipped - Discord's full module registry, use the search tools for this)`);return}if(typeof r=="object"){if(a.has(r)){n.push(`${c} -> [already listed elsewhere, circular]`);return}a.add(r)}let d;try{d=Object.keys(r).sort()}catch(i){n.push(`${c} -> [couldn't read keys: ${i}]`);return}const l=d.slice(0,60);for(const i of l){const f=`${c}.${i}`;let y;try{y=r[i]}catch($){n.push(`${f} -> [threw on access: ${$}]`);continue}const R=L(y);n.push(`${f} (${R})`),R==="object"&&u60&&n.push(`${c} -> (+${d.length-60} more keys not shown at this level)`)}try{o(globalThis.vendetta,"vendetta",0)}catch(r){n.push(`Error walking the vendetta object: ${r}`)}return n.length?n.join(` -`):"vendetta object not found or empty"}function Y(t){if(t===void 0)return"undefined";if(t===null)return"null";if(typeof t=="function")return`[Function: ${t.name||"anonymous"}]`;if(typeof t!="object")return String(t);const a=new WeakSet;try{return JSON.stringify(t,function(n,o){if(typeof o=="function")return`[Function: ${o.name||"anonymous"}]`;if(typeof o=="symbol")return o.toString();if(typeof o=="object"&&o!==null){if(a.has(o))return"[Circular]";a.add(o)}return o},2)}catch{try{return`[unserializable object, keys: ${Object.keys(t).join(", ")}]`}catch(n){return`[unserializable, and Object.keys threw: ${n}]`}}}function K(t){return t.replace(/[‘’]/g,"'").replace(/[“”]/g,'"').replace(/[–—]/g,"-")}async function q(t){const a=K(t);try{const n=new Function("findByProps","findByName","findByTypeName","findByStoreName","findByPropsAll","findByNameAll","find","rawFind","rawFindByTypeName","rawFindByProps","rawFindByName","rawFindByStoreName","instead","before","after","getAssetIDByName","showToast","React","ReactNative","FluxDispatcher","window",`return (function() { -${a} -})();`)(s.findByProps,s.findByName,s.findByTypeName,s.findByStoreName,s.findByPropsAll,s.findByNameAll,s.find,S,T,P,m,C,v.instead,v.before,v.after,F.getAssetIDByName,p.showToast,e.React,e.ReactNative,e.FluxDispatcher,window),o=n&&typeof n.then=="function"?await n:n;return Y(o)}catch(n){return`Error: ${n instanceof Error?`${n.message} -${n.stack??""}`:String(n)}`}}const J=500;function X(t,a){return new Promise(function(n){const o=new Map;let r=function(){},c=!1;const u=function(){if(c)return;c=!0,r();const d=a?.trim(),l=[...o.entries()].sort(function(i,f){return f[1]-i[1]}).map(function([i,f]){return`${String(f).padStart(5)} ${i}`});n(l.length?`${o.size} distinct type(s)${d?` matching "${d}"`:""} over ${t}ms: +(function(E,e,r,y,k,R,w,F){"use strict";const{ScrollView:A,View:_}=e.ReactNative;function O({children:t}){return e.React.createElement(A,{style:{flex:1}},t,e.React.createElement(_,{style:{height:24}}))}const{View:j,Text:I}=e.ReactNative;function D({children:t,style:i}){return e.React.createElement(j,{style:[{marginHorizontal:16,marginVertical:8,padding:10,borderRadius:8,borderWidth:1,borderColor:"rgba(128,128,128,0.25)"},i]},e.React.createElement(I,{style:{fontSize:12.5,lineHeight:18,opacity:.75}},t))}const{TouchableOpacity:z,Text:H}=e.ReactNative;function h({label:t,onPress:i,disabled:n,style:l}){return e.React.createElement(z,{disabled:n,onPress:i,style:[{backgroundColor:"#5865F2",borderRadius:8,padding:10,alignItems:"center",opacity:n?.5:1},l]},e.React.createElement(H,{style:{color:"white",fontWeight:"600"}},t))}function P(t){const i=window?.modules;if(i)for(const n in i){const l=i[n];if(!l?.isInitialized)continue;const a=l.publicModule?.exports;if(a)try{if(t(a))return a;if(a.default!=null&&t(a.default))return a.default}catch{}}}function $(t){return P(function(i){return i?.name===t||i?.displayName===t||i?.type?.name===t||i?.type?.displayName===t})}function m(t){return P(function(i){return i?.name===t||i?.displayName===t})}function T(...t){return P(function(i){return t.every(function(n){return i?.[n]!==void 0})})}function C(t){return P(function(i){return typeof i?.getName=="function"&&i.getName.length===0&&i.getName()===t})}const x=[{label:'findByProps("computePermissions", "canEveryoneRole")',run:function(){return r.findByProps("computePermissions","canEveryoneRole")}},{label:'findByProps("getBotLabel")',run:function(){return r.findByProps("getBotLabel")}},{label:'findByName("DisplayName", false)',run:function(){return r.findByName("DisplayName",!1)}},{label:'findByName("HeaderName", false)',run:function(){return r.findByName("HeaderName",!1)}},{label:'findByName("getTagProperties", false)',run:function(){return r.findByName("getTagProperties",!1)}},{label:'findByTypeNameAll("UserRow")',run:function(){return r.findByTypeNameAll("UserRow")}},{label:'findByStoreName("ThemeStore")',run:function(){return r.findByStoreName("ThemeStore")}},{label:'findByStoreName("GuildMemberStore")',run:function(){return r.findByStoreName("GuildMemberStore")}},{label:'findByStoreName("GuildStore")',run:function(){return r.findByStoreName("GuildStore")}},{label:'findByStoreName("ChannelStore")',run:function(){return r.findByStoreName("ChannelStore")}},{label:'findByStoreName("UserStore")',run:function(){return r.findByStoreName("UserStore")}},{label:'findByStoreName("RelationshipStore")',run:function(){return r.findByStoreName("RelationshipStore")}},{label:'findByName("RowManager", false)',run:function(){return r.findByName("RowManager",!1)}},{label:'findByProps("TYPING_WRAPPER_HEIGHT")',run:function(){return r.findByProps("TYPING_WRAPPER_HEIGHT")}},{label:'findByName("VoiceUserConnected", false)',run:function(){return r.findByName("VoiceUserConnected",!1)}},{label:"find(resolveSemanticColor via default.internal)",run:function(){return r.find(function(t){return t?.default?.internal?.resolveSemanticColor})}},{label:"find(resolveSemanticColor via meta)",run:function(){return r.find(function(t){return t?.meta?.resolveSemanticColor})}},{label:"find(UserProfileContent)",run:function(){return r.find(function(t){return t?.type?.name==="UserProfileContent"})}},{label:"find(UserProfile)",run:function(){return r.find(function(t){return t?.type?.name==="UserProfile"})}},{label:'findByName("UserProfileSection", false)',run:function(){return r.findByName("UserProfileSection",!1)}},{label:'findByProps("sendMessage", "sendBotMessage")',run:function(){return r.findByProps("sendMessage","sendBotMessage")}},{label:'findByProps("sendBotMessage") (single prop, matches Revenge core)',run:function(){return r.findByProps("sendBotMessage")}},{label:'findByProps("openLazy", "hideActionSheet")',run:function(){return r.findByProps("openLazy","hideActionSheet")}},{label:'findByProps("push", "pushLazy", "pop")',run:function(){return r.findByProps("push","pushLazy","pop")}},{label:'findByProps("getRenderCloseButton")',run:function(){return r.findByProps("getRenderCloseButton")}},{label:'findByProps("getHeaderCloseButton")',run:function(){return r.findByProps("getHeaderCloseButton")}},{label:'findByName("Navigator")',run:function(){return r.findByName("Navigator")}},{label:'findByName("ThemedRolePill", false)',run:function(){return r.findByName("ThemedRolePill",!1)}},{label:'findByName("RolePill", false)',run:function(){return r.findByName("RolePill",!1)}},{label:'findByProps("saveProfileChanges")',run:function(){return r.findByProps("saveProfileChanges")}},{label:'findByProps("useAvatarColors")',run:function(){return r.findByProps("useAvatarColors")}},{label:'findByProps("useThemeContext")',run:function(){return r.findByProps("useThemeContext")}},{label:'findByProps("getProfileTheme")',run:function(){return r.findByProps("getProfileTheme")}},{label:'findByProps("ThemeContextProvider")',run:function(){return r.findByProps("ThemeContextProvider")}},{label:'findByName("ProfileEffectRecord", false)',run:function(){return r.findByName("ProfileEffectRecord",!1)}},{label:'findByStoreName("UserProfileStore")',run:function(){return r.findByStoreName("UserProfileStore")}},{label:'findByStoreName("CollectiblesPurchaseStore")',run:function(){return r.findByStoreName("CollectiblesPurchaseStore")}},{label:'findByStoreName("ProfileEffectStore")',run:function(){return r.findByStoreName("ProfileEffectStore")}},{label:'findByName("GuildProfileEditForm", false) (currently dead/unused patch)',run:function(){return r.findByName("GuildProfileEditForm",!1)}},{label:'findByName("UserProfileEditForm", false)',run:function(){return r.findByName("UserProfileEditForm",!1)}},{label:'findByName("useProfileTheme", false)',run:function(){return r.findByName("useProfileTheme",!1)}},{label:'findByName("useProfileThemeColors", false)',run:function(){return r.findByName("useProfileThemeColors",!1)}},{label:'findByPropsAll("NONE_ITEM")',run:function(){return r.findByPropsAll("NONE_ITEM")}},{label:'findByProps("Radius")',run:function(){return r.findByProps("Radius")}},{label:'findByProps("Spacing")',run:function(){return r.findByProps("Spacing")}},{label:'findByProps("SafeAreaContext")',run:function(){return r.findByProps("SafeAreaContext")}},{label:'findByName("useWindowDimensions")',run:function(){return r.findByName("useWindowDimensions")}},{label:'findByProps("IconSizes")',run:function(){return r.findByProps("IconSizes")}},{label:'findByName("FlashList")',run:function(){return r.findByName("FlashList")}},{label:'findByProps("Svg")',run:function(){return r.findByProps("Svg")}},{label:'findByProps("PressableOpacity")',run:function(){return r.findByProps("PressableOpacity")}},{label:'findByProps("TextStyleSheet")',run:function(){return r.findByProps("TextStyleSheet")}},{label:'findByProps("BottomSheet")',run:function(){return r.findByProps("BottomSheet")}},{label:'findByProps("ActionSheet")',run:function(){return r.findByProps("ActionSheet")}},{label:'findByProps("BottomSheetScrollView")',run:function(){return r.findByProps("BottomSheetScrollView")}},{label:'findByProps("showActionSheet")',run:function(){return r.findByProps("showActionSheet")}},{label:'findByName("EditProfileEffectActionSheet")',run:function(){return r.findByName("EditProfileEffectActionSheet")}},{label:'findByName("showCustomColorPickerActionSheet")',run:function(){return r.findByName("showCustomColorPickerActionSheet")}},{label:'findByProps("triggerHapticFeedback")',run:function(){return r.findByProps("triggerHapticFeedback")}},{label:"semanticColors.HEADER_SECONDARY",run:function(){return R.semanticColors?.HEADER_SECONDARY}},{label:"semanticColors.BACKGROUND_ACCENT",run:function(){return R.semanticColors?.BACKGROUND_ACCENT}},{label:"semanticColors.BACKGROUND_PRIMARY",run:function(){return R.semanticColors?.BACKGROUND_PRIMARY}},{label:"semanticColors.BACKGROUND_FLOATING",run:function(){return R.semanticColors?.BACKGROUND_FLOATING}},{label:"semanticColors.BUTTON_OUTLINE_BRAND_BORDER_ACTIVE",run:function(){return R.semanticColors?.BUTTON_OUTLINE_BRAND_BORDER_ACTIVE}},{label:"semanticColors.TEXT_NORMAL",run:function(){return R.semanticColors?.TEXT_NORMAL}}];function M(t){if(t==null)return"NOT FOUND";if(typeof t=="object"){const i=Object.keys(t);return`found (${i.length} key${i.length===1?"":"s"})`}return`found (${typeof t})`}function U(){return x.map(function({label:t,run:i}){try{const n=i();return{label:t,found:n!=null,detail:M(n)}}catch(n){return{label:t,found:!1,detail:`threw: ${n}`}}})}function V(t){const i=t.filter(function(n){return!n.found});return[`Key Inspector report - ${new Date().toISOString()}`,`${t.length} checked, ${i.length} missing`,"",...t.map(function(n){return`[${n.found?"OK":"MISSING"}] ${n.label} -> ${n.detail}`}),"",`semanticColors keys (${Object.keys(R.semanticColors??{}).length}):`,...Object.keys(R.semanticColors??{}).sort(),"",`rawColors keys (${Object.keys(R.rawColors??{}).length}):`,...Object.keys(R.rawColors??{}).sort()].join(` +`)}const G=new Set(["vendetta.metro.modules"]);function L(t){return t===null?"null":t===void 0?"undefined":Array.isArray(t)?`array(${t.length})`:typeof t}function W(t=3){const i=new WeakSet,n=[];function l(a,c,u){if(a==null||typeof a!="object"&&typeof a!="function")return;if(G.has(c)){n.push(`${c} -> (skipped - Discord's full module registry, use the search tools for this)`);return}if(typeof a=="object"){if(i.has(a)){n.push(`${c} -> [already listed elsewhere, circular]`);return}i.add(a)}let d;try{d=Object.keys(a).sort()}catch(o){n.push(`${c} -> [couldn't read keys: ${o}]`);return}const s=d.slice(0,60);for(const o of s){const f=`${c}.${o}`;let p;try{p=a[o]}catch(v){n.push(`${f} -> [threw on access: ${v}]`);continue}const B=L(p);n.push(`${f} (${B})`),B==="object"&&u60&&n.push(`${c} -> (+${d.length-60} more keys not shown at this level)`)}try{l(globalThis.vendetta,"vendetta",0)}catch(a){n.push(`Error walking the vendetta object: ${a}`)}return n.length?n.join(` +`):"vendetta object not found or empty"}function Y(t){if(t===void 0)return"undefined";if(t===null)return"null";if(typeof t=="function")return`[Function: ${t.name||"anonymous"}]`;if(typeof t!="object")return String(t);const i=new WeakSet;try{return JSON.stringify(t,function(n,l){if(typeof l=="function")return`[Function: ${l.name||"anonymous"}]`;if(typeof l=="symbol")return l.toString();if(typeof l=="object"&&l!==null){if(i.has(l))return"[Circular]";i.add(l)}return l},2)}catch{try{return`[unserializable object, keys: ${Object.keys(t).join(", ")}]`}catch(n){return`[unserializable, and Object.keys threw: ${n}]`}}}function K(t){return t.replace(/[‘’]/g,"'").replace(/[“”]/g,'"').replace(/[–—]/g,"-")}async function q(t){const i=K(t);try{const n=new Function("findByProps","findByName","findByTypeName","findByStoreName","findByPropsAll","findByNameAll","find","rawFind","rawFindByTypeName","rawFindByProps","rawFindByName","rawFindByStoreName","instead","before","after","getAssetIDByName","showToast","React","ReactNative","FluxDispatcher","window",`return (function() { +${i} +})();`)(r.findByProps,r.findByName,r.findByTypeName,r.findByStoreName,r.findByPropsAll,r.findByNameAll,r.find,P,$,T,m,C,w.instead,w.before,w.after,F.getAssetIDByName,y.showToast,e.React,e.ReactNative,e.FluxDispatcher,window),l=n&&typeof n.then=="function"?await n:n;return Y(l)}catch(n){return`Error: ${n instanceof Error?`${n.message} +${n.stack??""}`:String(n)}`}}const J=500;function X(t,i){return new Promise(function(n){const l=new Map;let a=function(){},c=!1;const u=function(){if(c)return;c=!0,a();const d=i?.trim(),s=[...l.entries()].sort(function(o,f){return f[1]-o[1]}).map(function([o,f]){return`${String(f).padStart(5)} ${o}`});n(s.length?`${l.size} distinct type(s)${d?` matching "${d}"`:""} over ${t}ms: -${l.join(` -`)}`:`(no${d?` matching "${d}"`:""} events fired during the ${t}ms capture window)`)};try{r=v.before("dispatch",e.FluxDispatcher,function(d){const l=d[0]?.type??"(no type)",i=a?.trim();i&&!l.includes(i)||!o.has(l)&&o.size>=J||o.set(l,(o.get(l)??0)+1)})}catch(d){n(`Failed to patch FluxDispatcher.dispatch: ${d}`);return}setTimeout(u,t)})}function Q(t){try{return JSON.stringify(t,function(a,n){return typeof n=="function"?`[Function: ${n.name||"anonymous"}]`:n},2)}catch{try{return`[unserializable, keys: ${Object.keys(t??{}).join(", ")}]`}catch{return String(t)}}}function Z(t,a,n){return new Promise(function(o){const r=t.trim(),c=s.findByTypeName(r)??s.findByName(r,!1);if(!c){o(`"${r}" not found via findByTypeName or findByName.`);return}if(typeof c.type!="function"){o(`Found "${r}", but it has no callable .type property (not a memo/forwardRef wrapper), so its own render calls can't be intercepted this way. Its keys: ${Object.keys(c).join(", ")}`);return}const u=[];let d=!1,l=function(){};const i=function(){d||(d=!0,l(),o(u.length?u.join(` +${s.join(` +`)}`:`(no${d?` matching "${d}"`:""} events fired during the ${t}ms capture window)`)};try{a=w.before("dispatch",e.FluxDispatcher,function(d){const s=d[0]?.type??"(no type)",o=i?.trim();o&&!s.includes(o)||!l.has(s)&&l.size>=J||l.set(s,(l.get(s)??0)+1)})}catch(d){n(`Failed to patch FluxDispatcher.dispatch: ${d}`);return}setTimeout(u,t)})}function Q(t){try{return JSON.stringify(t,function(i,n){return typeof n=="function"?`[Function: ${n.name||"anonymous"}]`:n},2)}catch{try{return`[unserializable, keys: ${Object.keys(t??{}).join(", ")}]`}catch{return String(t)}}}function Z(t,i,n){return new Promise(function(l){const a=t.trim(),c=r.findByTypeName(a)??r.findByName(a,!1);if(!c){l(`"${a}" not found via findByTypeName or findByName.`);return}if(typeof c.type!="function"){l(`Found "${a}", but it has no callable .type property (not a memo/forwardRef wrapper), so its own render calls can't be intercepted this way. Its keys: ${Object.keys(c).join(", ")}`);return}const u=[];let d=!1,s=function(){};const o=function(){d||(d=!0,s(),l(u.length?u.join(` --- -`):`"${r}" never rendered during the ${n}ms capture window.`))};try{l=v.before("type",c,function(f){u.push(`Call ${u.length+1} props: -${Q(f[0])}`),u.length>=a&&i()})}catch(f){o(`Failed to patch "${r}": ${f}`);return}setTimeout(i,n)})}const{View:w,Text:g}=e.ReactNative,{FormSection:N,FormInput:b}=k.Forms;function ee(){const[t,a]=e.React.useState(null);return e.React.createElement(N,{title:"Full diagnostic scan"},e.React.createElement(w,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(h,{label:"Run scan & copy full report",onPress:function(){const n=U(),o=n.filter(function(r){return!r.found}).length;e.clipboard.setString(V(n)),a(`${n.length} checked, ${o} missing - full report copied`),p.showToast(`${o} missing out of ${n.length} - report copied`,void 0)}}),t&&e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},t)))}function te(){const[t,a]=e.React.useState(""),[n,o]=e.React.useState(null),[r,c]=e.React.useState(!1),u=async function(){if(!(!t.trim()||r)){c(!0);try{const d=await q(t);o(d),e.clipboard.setString(d),p.showToast("Result copied",void 0)}finally{c(!1)}}};return e.React.createElement(N,{title:"Eval"},e.React.createElement(w,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"Code",placeholder:'e.g. return findByProps("getRootNavigationRef")',value:t,onChange:a,multiline:!0,autoCorrect:!1,autoCapitalize:"none",spellCheck:!1}),e.React.createElement(h,{label:r?"Running...":"Run & copy result",style:{marginTop:8},disabled:r,onPress:u}),n!=null&&e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.85},selectable:!0},n.length>2e3?`${n.slice(0,2e3)} -... (truncated, full result copied)`:n),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Runs as a plain (non-async) function body - a bare expression or `return ...` works, but not the async/await keywords (Hermes doesn't support those in dynamically-eval'd code). For timed/async checks, return a Promise built with a plain function instead of an arrow/async function - it gets awaited for you outside the sandbox. In scope: findByProps/findByName/ findByTypeName/findByStoreName/findByPropsAll/findByNameAll/find, the raw* passive variants (rawFind/rawFindByTypeName/rawFindByProps/rawFindByName/ rawFindByStoreName), instead/before/after, getAssetIDByName, showToast, React, ReactNative, FluxDispatcher, and window. Nothing runs until you tap the button.")))}function ne(){const[t,a]=e.React.useState(""),[n,o]=e.React.useState("10"),[r,c]=e.React.useState(null),[u,d]=e.React.useState(!1),l=async function(){if(u)return;const i=Math.max(1,Number(n)||10)*1e3;d(!0),c(null),p.showToast(`Capturing Flux events for ${i/1e3}s - go do the thing...`,void 0);try{const f=await X(i,t);c(f),e.clipboard.setString(f),p.showToast("Capture done - report copied",void 0)}finally{d(!1)}};return e.React.createElement(N,{title:"Flux event logger"},e.React.createElement(w,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"Filter (optional substring, e.g. GUILD)",placeholder:"Leave blank to capture everything",value:t,onChange:a}),e.React.createElement(b,{title:"Capture duration (seconds)",placeholder:"10",value:n,onChange:o,keyboardType:"numeric"}),e.React.createElement(h,{label:u?"Capturing...":"Start capture",style:{marginTop:8},disabled:u,onPress:l}),r!=null&&e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.85},selectable:!0},r.length>2e3?`${r.slice(0,2e3)} -... (truncated, full report copied)`:r),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Tap start, then go do the thing you're trying to understand (open a screen, send a message, tap a button) before the window closes. Reports every action type that dispatched, sorted by count - the fastest way to find which event to hook into instead of guessing from decompiled source.")))}function re(){const[t,a]=e.React.useState(""),[n,o]=e.React.useState("3"),[r,c]=e.React.useState("15"),[u,d]=e.React.useState(null),[l,i]=e.React.useState(!1),f=async function(){const y=t.trim();if(!y||l)return;const R=Math.max(1,Number(r)||15)*1e3;i(!0),d(null);try{const $=await Z(y,Math.max(1,Number(n)||3),R);d($),e.clipboard.setString($),p.showToast("Capture done - result copied",void 0)}finally{i(!1)}};return e.React.createElement(N,{title:"Component render/props logger"},e.React.createElement(w,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"Component name (findByTypeName / findByName)",placeholder:"e.g. YouBarNotificationsButton",value:t,onChange:a}),e.React.createElement(b,{title:"Max renders to capture",placeholder:"3",value:n,onChange:o,keyboardType:"numeric"}),e.React.createElement(b,{title:"Give up after (seconds)",placeholder:"15",value:r,onChange:c,keyboardType:"numeric"}),e.React.createElement(h,{label:l?"Waiting for renders...":"Start capture",style:{marginTop:8},disabled:l,onPress:f}),u!=null&&e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.85},selectable:!0},u.length>2e3?`${u.slice(0,2e3)} -... (truncated, full result copied)`:u),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Patches the component to log its actual props on every render, up to the call cap or the time limit. Only works for React.memo/forwardRef-wrapped components (most of what findByTypeName/findByName return) - a bare function component has no property to intercept its own calls through.")))}function ae(){const[t,a]=e.React.useState(""),[n,o]=e.React.useState(""),[r,c]=e.React.useState(""),[u,d]=e.React.useState(""),l=function(i,f){try{const y=f();if(!y){e.clipboard.setString(`${i} -> not found`),p.showToast("Not found - copied that result",void 0);return}const R=Object.keys(y).sort();e.clipboard.setString(`${i} -> found, keys: -${R.join(` -`)}`),p.showToast(`Found it - copied ${R.length} key(s)`,void 0)}catch(y){e.clipboard.setString(`Error running ${i}: ${y}`),p.showToast("Search failed - copied the error instead",void 0)}};return e.React.createElement(N,{title:"Raw search (bypasses the negative-result cache)"},e.React.createElement(w,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"rawFindByProps - comma-separated prop names",placeholder:"e.g. getRootNavigationRef",value:t,onChange:a}),e.React.createElement(h,{label:"Search & copy result",style:{marginTop:8,marginBottom:16},onPress:function(){const i=t.split(",").map(function(f){return f.trim()}).filter(Boolean);i.length&&l(`rawFindByProps(${i.join(", ")})`,function(){return P(...i)})}}),e.React.createElement(b,{title:"rawFindByName",placeholder:"e.g. YouBarNotificationsButton",value:n,onChange:o}),e.React.createElement(h,{label:"Search & copy result",style:{marginTop:8,marginBottom:16},onPress:function(){return n.trim()&&l(`rawFindByName("${n.trim()}")`,function(){return m(n.trim())})}}),e.React.createElement(b,{title:"rawFindByTypeName",placeholder:"e.g. YouBarNotificationsButton",value:r,onChange:c}),e.React.createElement(h,{label:"Search & copy result",style:{marginTop:8,marginBottom:16},onPress:function(){return r.trim()&&l(`rawFindByTypeName("${r.trim()}")`,function(){return T(r.trim())})}}),e.React.createElement(b,{title:"rawFindByStoreName",placeholder:"e.g. GuildStore",value:u,onChange:d}),e.React.createElement(h,{label:"Search & copy result",style:{marginTop:8},onPress:function(){return u.trim()&&l(`rawFindByStoreName("${u.trim()}")`,function(){return C(u.trim())})}}),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},`Revenge's own findByProps/findByName/findByTypeName/findByStoreName cache a negative result forever the first time a search comes up empty, and never rescan - so if a module hasn't been required yet when you search, it can look "missing" permanently for the rest of the session even after it registers. These raw* variants only ever read modules Metro's own isInitialized flag says are already loaded (never force-requiring anything), so re-running one after doing the thing that loads your target module will actually find it.`)))}function ie(){const[t,a]=e.React.useState("Not captured yet - scroll this section into view (or reopen this screen) to trigger the ref."),n=function(o){if(o)try{let r=null,c="";if(o._internalFiberInstanceHandleDEV)r=o._internalFiberInstanceHandleDEV,c="_internalFiberInstanceHandleDEV";else if(o._internalInstanceHandle)r=o._internalInstanceHandle,c="_internalInstanceHandle";else if(o.__internalInstanceHandle)r=o.__internalInstanceHandle,c="__internalInstanceHandle";else{const l=Object.keys(o).find(function(i){return i.startsWith("__reactFiber$")||i.startsWith("__reactInternalInstance$")});l&&(r=o[l],c=l)}if(!r){a(`No fiber pointer found on the instance. Instance keys: ${Object.keys(o).join(", ")||"(none)"}`);return}if(r.return===void 0&&r.child===void 0){const l=r.stateNode??r.fiber??r._debugOwner;if(l&&(l.return!==void 0||l.child!==void 0))r=l,c+=" (via nested property)";else{a(`Found "${c}" but it doesn't look fiber-shaped (no .return/.child). Its keys: ${Object.keys(r).join(", ")||"(none)"}`);return}}let u=r,d=0;for(;u.return&&d<5e3;)u=u.return,d++;window.__keyInspectorFiberRoot=u,window.__keyInspectorFiberSelf=r,a(`Captured via "${c}" (walked up ${d} level(s) to the root). window.__keyInspectorFiberRoot and window.__keyInspectorFiberSelf are now set - use Eval to walk them.`)}catch(r){a(`Error: ${r}`)}};return e.React.createElement(N,{title:"Fiber capture (for Eval)"},e.React.createElement(w,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(w,{ref:n,style:{width:1,height:1}}),e.React.createElement(g,{style:{fontSize:12.5,opacity:.85},selectable:!0},t),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Reads React's own internal fiber pointer directly off a native view instance - works without React DevTools (confirmed absent on this build), since it's the same internal linkage React itself relies on to route touch events, not an inspector-only feature. Walks up to the root fiber automatically so Eval can search the whole live tree (whatever's actually mounted right now, not module-registry guessing) from window.__keyInspectorFiberRoot afterward.")))}function oe(){return e.React.createElement(N,{title:"Full Vendetta API tree"},e.React.createElement(w,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(h,{label:"Copy the entire plugin API tree",onPress:function(){const t=W(3),a=t.split(` -`).length;e.clipboard.setString(t),p.showToast(`Copied ${a} lines - every key path under window.vendetta`,void 0)}}),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Every key path under the stable plugin API (window.vendetta), 3 levels deep - this is everything Revenge itself exposes to plugins, not Discord's raw internals (those are searchable individually below, since dumping all of them would be enormous).")))}function le(){const[t,a]=e.React.useState(""),[n,o]=e.React.useState(""),r=function(){const l=t.split(",").map(function(i){return i.trim()}).filter(Boolean);if(l.length)try{const i=s.findByProps(...l);if(!i){e.clipboard.setString(`findByProps(${l.join(", ")}) -> not found`),p.showToast("No module found - copied that result",void 0);return}const f=Object.keys(i).sort();e.clipboard.setString(`findByProps(${l.join(", ")}) -> found, keys: +`):`"${a}" never rendered during the ${n}ms capture window.`))};try{s=w.before("type",c,function(f){u.push(`Call ${u.length+1} props: +${Q(f[0])}`),u.length>=i&&o()})}catch(f){l(`Failed to patch "${a}": ${f}`);return}setTimeout(o,n)})}const{View:N,Text:g}=e.ReactNative,{FormSection:S,FormInput:b}=k.Forms;function ee(){const[t,i]=e.React.useState(null);return e.React.createElement(S,{title:"Full diagnostic scan"},e.React.createElement(N,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(h,{label:"Run scan & copy full report",onPress:function(){const n=U(),l=n.filter(function(a){return!a.found}).length;e.clipboard.setString(V(n)),i(`${n.length} checked, ${l} missing - full report copied`),y.showToast(`${l} missing out of ${n.length} - report copied`,void 0)}}),t&&e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},t)))}function te(){const[t,i]=e.React.useState(""),[n,l]=e.React.useState(null),[a,c]=e.React.useState(!1),u=async function(){if(!(!t.trim()||a)){c(!0);try{const d=await q(t);l(d),e.clipboard.setString(d),y.showToast("Result copied",void 0)}finally{c(!1)}}};return e.React.createElement(S,{title:"Eval"},e.React.createElement(N,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"Code",placeholder:'e.g. return findByProps("getRootNavigationRef")',value:t,onChange:i,multiline:!0,autoCorrect:!1,autoCapitalize:"none",spellCheck:!1}),e.React.createElement(h,{label:a?"Running...":"Run & copy result",style:{marginTop:8},disabled:a,onPress:u}),n!=null&&e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.85},selectable:!0},n.length>2e3?`${n.slice(0,2e3)} +... (truncated, full result copied)`:n),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Runs as a plain (non-async) function body - a bare expression or `return ...` works, but not the async/await keywords (Hermes doesn't support those in dynamically-eval'd code). For timed/async checks, return a Promise built with a plain function instead of an arrow/async function - it gets awaited for you outside the sandbox. In scope: findByProps/findByName/ findByTypeName/findByStoreName/findByPropsAll/findByNameAll/find, the raw* passive variants (rawFind/rawFindByTypeName/rawFindByProps/rawFindByName/ rawFindByStoreName), instead/before/after, getAssetIDByName, showToast, React, ReactNative, FluxDispatcher, and window. Nothing runs until you tap the button.")))}function ne(){const[t,i]=e.React.useState(""),[n,l]=e.React.useState("10"),[a,c]=e.React.useState(null),[u,d]=e.React.useState(!1),s=async function(){if(u)return;const o=Math.max(1,Number(n)||10)*1e3;d(!0),c(null),y.showToast(`Capturing Flux events for ${o/1e3}s - go do the thing...`,void 0);try{const f=await X(o,t);c(f),e.clipboard.setString(f),y.showToast("Capture done - report copied",void 0)}finally{d(!1)}};return e.React.createElement(S,{title:"Flux event logger"},e.React.createElement(N,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"Filter (optional substring, e.g. GUILD)",placeholder:"Leave blank to capture everything",value:t,onChange:i}),e.React.createElement(b,{title:"Capture duration (seconds)",placeholder:"10",value:n,onChange:l,keyboardType:"numeric"}),e.React.createElement(h,{label:u?"Capturing...":"Start capture",style:{marginTop:8},disabled:u,onPress:s}),a!=null&&e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.85},selectable:!0},a.length>2e3?`${a.slice(0,2e3)} +... (truncated, full report copied)`:a),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Tap start, then go do the thing you're trying to understand (open a screen, send a message, tap a button) before the window closes. Reports every action type that dispatched, sorted by count - the fastest way to find which event to hook into instead of guessing from decompiled source.")))}function re(){const[t,i]=e.React.useState(""),[n,l]=e.React.useState("3"),[a,c]=e.React.useState("15"),[u,d]=e.React.useState(null),[s,o]=e.React.useState(!1),f=async function(){const p=t.trim();if(!p||s)return;const B=Math.max(1,Number(a)||15)*1e3;o(!0),d(null);try{const v=await Z(p,Math.max(1,Number(n)||3),B);d(v),e.clipboard.setString(v),y.showToast("Capture done - result copied",void 0)}finally{o(!1)}};return e.React.createElement(S,{title:"Component render/props logger"},e.React.createElement(N,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"Component name (findByTypeName / findByName)",placeholder:"e.g. YouBarNotificationsButton",value:t,onChange:i}),e.React.createElement(b,{title:"Max renders to capture",placeholder:"3",value:n,onChange:l,keyboardType:"numeric"}),e.React.createElement(b,{title:"Give up after (seconds)",placeholder:"15",value:a,onChange:c,keyboardType:"numeric"}),e.React.createElement(h,{label:s?"Waiting for renders...":"Start capture",style:{marginTop:8},disabled:s,onPress:f}),u!=null&&e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.85},selectable:!0},u.length>2e3?`${u.slice(0,2e3)} +... (truncated, full result copied)`:u),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Patches the component to log its actual props on every render, up to the call cap or the time limit. Only works for React.memo/forwardRef-wrapped components (most of what findByTypeName/findByName return) - a bare function component has no property to intercept its own calls through.")))}function ae(){const[t,i]=e.React.useState(""),[n,l]=e.React.useState(""),[a,c]=e.React.useState(""),[u,d]=e.React.useState(""),s=function(o,f){try{const p=f();if(!p){e.clipboard.setString(`${o} -> not found`),y.showToast("Not found - copied that result",void 0);return}const B=Object.keys(p).sort();e.clipboard.setString(`${o} -> found, keys: +${B.join(` +`)}`),y.showToast(`Found it - copied ${B.length} key(s)`,void 0)}catch(p){e.clipboard.setString(`Error running ${o}: ${p}`),y.showToast("Search failed - copied the error instead",void 0)}};return e.React.createElement(S,{title:"Raw search (bypasses the negative-result cache)"},e.React.createElement(N,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"rawFindByProps - comma-separated prop names",placeholder:"e.g. getRootNavigationRef",value:t,onChange:i}),e.React.createElement(h,{label:"Search & copy result",style:{marginTop:8,marginBottom:16},onPress:function(){const o=t.split(",").map(function(f){return f.trim()}).filter(Boolean);o.length&&s(`rawFindByProps(${o.join(", ")})`,function(){return T(...o)})}}),e.React.createElement(b,{title:"rawFindByName",placeholder:"e.g. YouBarNotificationsButton",value:n,onChange:l}),e.React.createElement(h,{label:"Search & copy result",style:{marginTop:8,marginBottom:16},onPress:function(){return n.trim()&&s(`rawFindByName("${n.trim()}")`,function(){return m(n.trim())})}}),e.React.createElement(b,{title:"rawFindByTypeName",placeholder:"e.g. YouBarNotificationsButton",value:a,onChange:c}),e.React.createElement(h,{label:"Search & copy result",style:{marginTop:8,marginBottom:16},onPress:function(){return a.trim()&&s(`rawFindByTypeName("${a.trim()}")`,function(){return $(a.trim())})}}),e.React.createElement(b,{title:"rawFindByStoreName",placeholder:"e.g. GuildStore",value:u,onChange:d}),e.React.createElement(h,{label:"Search & copy result",style:{marginTop:8},onPress:function(){return u.trim()&&s(`rawFindByStoreName("${u.trim()}")`,function(){return C(u.trim())})}}),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},`Revenge's own findByProps/findByName/findByTypeName/findByStoreName cache a negative result forever the first time a search comes up empty, and never rescan - so if a module hasn't been required yet when you search, it can look "missing" permanently for the rest of the session even after it registers. These raw* variants only ever read modules Metro's own isInitialized flag says are already loaded (never force-requiring anything), so re-running one after doing the thing that loads your target module will actually find it.`)))}function ie(){const[t,i]=e.React.useState("Not captured yet - scroll this section into view (or reopen this screen) to trigger the ref."),n=function(l){if(l)try{let a=null,c="";if(l._internalFiberInstanceHandleDEV)a=l._internalFiberInstanceHandleDEV,c="_internalFiberInstanceHandleDEV";else if(l._internalInstanceHandle)a=l._internalInstanceHandle,c="_internalInstanceHandle";else if(l.__internalInstanceHandle)a=l.__internalInstanceHandle,c="__internalInstanceHandle";else{const s=Object.keys(l).find(function(o){return o.startsWith("__reactFiber$")||o.startsWith("__reactInternalInstance$")});s&&(a=l[s],c=s)}if(!a){i(`No fiber pointer found on the instance. Instance keys: ${Object.keys(l).join(", ")||"(none)"}`);return}if(a.return===void 0&&a.child===void 0){const s=a.stateNode??a.fiber??a._debugOwner;if(s&&(s.return!==void 0||s.child!==void 0))a=s,c+=" (via nested property)";else{i(`Found "${c}" but it doesn't look fiber-shaped (no .return/.child). Its keys: ${Object.keys(a).join(", ")||"(none)"}`);return}}let u=a,d=0;for(;u.return&&d<5e3;)u=u.return,d++;window.__keyInspectorFiberRoot=u,window.__keyInspectorFiberSelf=a,i(`Captured via "${c}" (walked up ${d} level(s) to the root). window.__keyInspectorFiberRoot and window.__keyInspectorFiberSelf are now set - use Eval to walk them.`)}catch(a){i(`Error: ${a}`)}};return e.React.createElement(S,{title:"Fiber capture (for Eval)"},e.React.createElement(N,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(N,{ref:n,style:{width:1,height:1}}),e.React.createElement(g,{style:{fontSize:12.5,opacity:.85},selectable:!0},t),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Reads React's own internal fiber pointer directly off a native view instance - works without React DevTools (confirmed absent on this build), since it's the same internal linkage React itself relies on to route touch events, not an inspector-only feature. Walks up to the root fiber automatically so Eval can search the whole live tree (whatever's actually mounted right now, not module-registry guessing) from window.__keyInspectorFiberRoot afterward.")))}function oe(){return e.React.createElement(S,{title:"Full Vendetta API tree"},e.React.createElement(N,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(h,{label:"Copy the entire plugin API tree",onPress:function(){const t=W(3),i=t.split(` +`).length;e.clipboard.setString(t),y.showToast(`Copied ${i} lines - every key path under window.vendetta`,void 0)}}),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},"Every key path under the stable plugin API (window.vendetta), 3 levels deep - this is everything Revenge itself exposes to plugins, not Discord's raw internals (those are searchable individually below, since dumping all of them would be enormous).")))}function le(){const[t,i]=e.React.useState(""),[n,l]=e.React.useState(""),a=function(){const s=t.split(",").map(function(o){return o.trim()}).filter(Boolean);if(s.length)try{const o=r.findByProps(...s);if(!o){e.clipboard.setString(`findByProps(${s.join(", ")}) -> not found`),y.showToast("No module found - copied that result",void 0);return}const f=Object.keys(o).sort();e.clipboard.setString(`findByProps(${s.join(", ")}) -> found, keys: ${f.join(` -`)}`),p.showToast(`Found it - copied ${f.length} key(s)`,void 0)}catch(i){e.clipboard.setString(`Error searching for ${l.join(", ")}: ${i}`),p.showToast("Search failed - copied the error instead",void 0)}},c=function(){const l=n.trim();if(l)try{const i=s.findByName(l,!1);if(!i){e.clipboard.setString(`findByName("${l}") -> not found`),p.showToast("No component found - copied that result",void 0);return}const f=Object.keys(i).sort();e.clipboard.setString(`findByName("${l}") -> found, keys: +`)}`),y.showToast(`Found it - copied ${f.length} key(s)`,void 0)}catch(o){e.clipboard.setString(`Error searching for ${s.join(", ")}: ${o}`),y.showToast("Search failed - copied the error instead",void 0)}},c=function(){const s=n.trim();if(s)try{const o=r.findByName(s,!1);if(!o){e.clipboard.setString(`findByName("${s}") -> not found`),y.showToast("No component found - copied that result",void 0);return}const f=Object.keys(o).sort();e.clipboard.setString(`findByName("${s}") -> found, keys: ${f.join(` -`)}`),p.showToast(`Found it - copied ${f.length} key(s)`,void 0)}catch(i){e.clipboard.setString(`Error searching for "${l}": ${i}`),p.showToast("Search failed - copied the error instead",void 0)}},u=function(){const l=t.split(",").map(function(i){return i.trim()}).filter(Boolean);if(l.length)try{const i=s.findByPropsAll(...l)??[],f=i.map(function(y,R){return`[${R}] keys: ${Object.keys(y).sort().join(", ")}`}).join(` +`)}`),y.showToast(`Found it - copied ${f.length} key(s)`,void 0)}catch(o){e.clipboard.setString(`Error searching for "${s}": ${o}`),y.showToast("Search failed - copied the error instead",void 0)}},u=function(){const s=t.split(",").map(function(o){return o.trim()}).filter(Boolean);if(s.length)try{const o=r.findByPropsAll(...s)??[],f=o.map(function(p,B){return`[${B}] keys: ${Object.keys(p).sort().join(", ")}`}).join(` -`);e.clipboard.setString(`findByPropsAll(${l.join(", ")}) -> ${i.length} match(es) +`);e.clipboard.setString(`findByPropsAll(${s.join(", ")}) -> ${o.length} match(es) -${f}`),p.showToast(`${i.length} match(es) - report copied`,void 0)}catch(i){e.clipboard.setString(`Error searching for ${l.join(", ")}: ${i}`),p.showToast("Search failed - copied the error instead",void 0)}},d=function(){const l=n.trim();if(l)try{const i=s.findByNameAll(l,!1)??[],f=i.map(function(y,R){return`[${R}] keys: ${Object.keys(y).sort().join(", ")}`}).join(` +${f}`),y.showToast(`${o.length} match(es) - report copied`,void 0)}catch(o){e.clipboard.setString(`Error searching for ${s.join(", ")}: ${o}`),y.showToast("Search failed - copied the error instead",void 0)}},d=function(){const s=n.trim();if(s)try{const o=r.findByNameAll(s,!1)??[],f=o.map(function(p,B){return`[${B}] keys: ${Object.keys(p).sort().join(", ")}`}).join(` -`);e.clipboard.setString(`findByNameAll("${l}") -> ${i.length} match(es) +`);e.clipboard.setString(`findByNameAll("${s}") -> ${o.length} match(es) -${f}`),p.showToast(`${i.length} match(es) - report copied`,void 0)}catch(i){e.clipboard.setString(`Error searching for "${l}": ${i}`),p.showToast("Search failed - copied the error instead",void 0)}};return e.React.createElement(N,{title:"One-off search"},e.React.createElement(w,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"findByProps - comma-separated prop names",placeholder:"e.g. sendMessage, sendBotMessage",value:t,onChange:a}),e.React.createElement(h,{label:"Search first match & copy",style:{marginTop:8},onPress:r}),e.React.createElement(h,{label:"Search ALL matches & copy",style:{marginTop:8,marginBottom:16},onPress:u}),e.React.createElement(b,{title:"findByName - component name",placeholder:"e.g. ThemedRolePill",value:n,onChange:o}),e.React.createElement(h,{label:"Search first match & copy",style:{marginTop:8},onPress:c}),e.React.createElement(h,{label:"Search ALL matches & copy",style:{marginTop:8},onPress:d}),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},'"ALL matches" is worth checking even when the first-match search succeeds - more than one module matching the same name/props is a common source of "found the wrong one" bugs (patching a re-export or an unrelated duplicate instead of the component actually on screen).')))}function se(){return e.React.createElement(_,null,e.React.createElement(ee,null),e.React.createElement(ie,null),e.React.createElement(ae,null),e.React.createElement(le,null),e.React.createElement(ne,null),e.React.createElement(re,null),e.React.createElement(te,null),e.React.createElement(oe,null),e.React.createElement(D,null,"The full scan checks every internal lookup this repo's plugins depend on (plus a few for plugins currently being fixed) in one pass, and includes the complete list of semanticColors/rawColors keys at the end. Paste the report back into chat when reporting a bug - it tells us exactly what's missing on your Discord version."))}var ce={settings:se};return E.default=ce,Object.defineProperty(E,"__esModule",{value:!0}),E})({},vendetta.metro.common,vendetta.metro,vendetta.ui.toasts,vendetta.ui.components,vendetta.ui,vendetta.patcher,vendetta.ui.assets); +${f}`),y.showToast(`${o.length} match(es) - report copied`,void 0)}catch(o){e.clipboard.setString(`Error searching for "${s}": ${o}`),y.showToast("Search failed - copied the error instead",void 0)}};return e.React.createElement(S,{title:"One-off search"},e.React.createElement(N,{style:{paddingHorizontal:16,paddingVertical:8}},e.React.createElement(b,{title:"findByProps - comma-separated prop names",placeholder:"e.g. sendMessage, sendBotMessage",value:t,onChange:i}),e.React.createElement(h,{label:"Search first match & copy",style:{marginTop:8},onPress:a}),e.React.createElement(h,{label:"Search ALL matches & copy",style:{marginTop:8,marginBottom:16},onPress:u}),e.React.createElement(b,{title:"findByName - component name",placeholder:"e.g. ThemedRolePill",value:n,onChange:l}),e.React.createElement(h,{label:"Search first match & copy",style:{marginTop:8},onPress:c}),e.React.createElement(h,{label:"Search ALL matches & copy",style:{marginTop:8},onPress:d}),e.React.createElement(g,{style:{marginTop:8,fontSize:12.5,opacity:.7}},'"ALL matches" is worth checking even when the first-match search succeeds - more than one module matching the same name/props is a common source of "found the wrong one" bugs (patching a re-export or an unrelated duplicate instead of the component actually on screen).')))}function se(){return e.React.createElement(O,null,e.React.createElement(ee,null),e.React.createElement(ie,null),e.React.createElement(ae,null),e.React.createElement(le,null),e.React.createElement(ne,null),e.React.createElement(re,null),e.React.createElement(te,null),e.React.createElement(oe,null),e.React.createElement(D,null,"The full scan checks every internal lookup this repo's plugins depend on (plus a few for plugins currently being fixed) in one pass, and includes the complete list of semanticColors/rawColors keys at the end. Paste the report back into chat when reporting a bug - it tells us exactly what's missing on your Discord version."))}var ce={settings:se};return E.default=ce,Object.defineProperty(E,"__esModule",{value:!0}),E})({},vendetta.metro.common,vendetta.metro,vendetta.ui.toasts,vendetta.ui.components,vendetta.ui,vendetta.patcher,vendetta.ui.assets); diff --git a/key-inspector/install/manifest.json b/key-inspector/install/manifest.json index cc5f83d..07d4ac7 100644 --- a/key-inspector/install/manifest.json +++ b/key-inspector/install/manifest.json @@ -1 +1 @@ -{"name":"Key Inspector","description":"Plugin-dev toolkit: on-device module search (incl. a cache-safe raw mode), a Flux event logger, a component render/props logger, an eval console, and full API/color-token dumps - for diagnosing and building plugins without needing a computer.","authors":[{"name":"everestmcarthur"}],"main":"index.js","hash":"c3a24cb638cb48c931a9b0bfe34afd60f795be609ea0bbc587bd1d5de752ac3f"} \ No newline at end of file +{"name":"Key Inspector","description":"Plugin-dev toolkit: on-device module search (incl. a cache-safe raw mode), a Flux event logger, a component render/props logger, an eval console, and full API/color-token dumps - for diagnosing and building plugins without needing a computer.","authors":[{"name":"everestmcarthur"}],"main":"index.js","hash":"55a7be951b7aa5f16d664bf02517120f95648b1eef4f792ac3f03c9b345fc30d"} \ No newline at end of file diff --git a/server-drawer/install/index.js b/server-drawer/install/index.js index 98707ed..a6c99cd 100644 --- a/server-drawer/install/index.js +++ b/server-drawer/install/index.js @@ -1 +1 @@ -(function(M,oe,h,c,r,i,ie,I,z,le,qe){"use strict";function m(e){const t=window?.modules;if(t)for(const n in t){const o=t[n];if(!o?.isInitialized)continue;const l=o.publicModule?.exports;if(l)try{if(e(l))return l;if(l.default!=null&&e(l.default))return l.default}catch{}}}function Xe(e){return m(function(t){return t?.name===e||t?.displayName===e})}function T(...e){return m(function(t){return e.every(function(n){return typeof t?.[n]=="function"})})}function U(e){const t=Object.keys(e);return m(function(n){return t.every(function(o){try{return e[o](n?.[o])}catch{return!1}})})}function b(e){return m(function(t){return typeof t?.getName=="function"&&t.getName.length===0&&t.getName()===e})}function Je(e,t,n=100){let o=!1,l;const s=e();return s?(t(s),{cancel(){}}):(l=setInterval(function(){if(o)return;const u=e();u&&(o=!0,clearInterval(l),t(u))},n),{cancel(){o=!0,l&&clearInterval(l)}})}const se=new Map,ke=[],ue=[];let v=[],W=!1;function Q(e,t,n){se.set(e,{replacement:t,extraProps:n})}function Ye(e,t){ue.push({predicate:e,transform:t})}function ae(e,t,n){v.push({predicate:e,onDetected:t,persistent:n?.persistent??!1})}function Ke(e){if(v.length===0)return;const t=[];for(const n of v){let o=!1;try{o=n.predicate(e)}catch{}if(o){try{n.onDetected(e)}catch{}n.persistent&&t.push(n)}else t.push(n)}v=t}function Ie(e,t){Ke(e);let n=t;if(n)for(const{predicate:l,transform:s}of ue)try{l(n)&&(n=s(n))}catch{}if(n)for(const{predicate:l,replacement:s}of ke)try{if(l(n))return s?{type:s,props:n}:null}catch{}const o=se.get(e);if(o)return{type:o.replacement,props:o.extraProps?{...n,...o.extraProps}:n};if(n!==t)return{type:e,props:n}}function Ze(e){if(W)return;const t=c.React.createElement;if(!t){console.warn("[ServerDrawer] React.createElement is null, skipping patch");return}const n=function(s,u,...g){const p=Ie(s,u);return p===null?null:p?t.call(c.React,p.type,p.props,...g):t.call(c.React,s,u,...g)};Object.assign(n,t),c.React.createElement=n,W=!0;const o=[],l=Je(function(){return m(function(s){return typeof s?.jsx=="function"&&typeof s?.jsxs=="function"&&"Fragment"in s})},function(s){for(const u of["jsx","jsxs"]){const g=s[u];typeof g=="function"&&(s[u]=function(p,S,...y){const d=Ie(p,S);return d===null?null:d?g.call(this,d.type,d.props,...y):g.call(this,p,S,...y)},o.push(function(){s[u]=g}))}});e.push(function(){l.cancel(),W&&(c.React.createElement=t,W=!1),o.forEach(function(s){return s()}),se.clear(),ke.length=0,ue.length=0,v=[]})}const $e="[ServerDrawer]";function Ne(e){return Ye(function(t){const n=t?.value;return!!(n&&typeof n=="object"&&"isRendered"in n&&"isVisibleToUser"in n&&"quest"in n)},function(t){const n=t.value,o=n.quest??et();return{...t,value:{...n,isRendered:!0,isVisibleToUser:!0,quest:tt(o)}}}),e.push(function(){}),console.log($e,"PATCH: watching for the Quest Dock coordination context"),!0}function et(){return{id:"server-drawer",config:{quest_content_type:0,assets:{questBarHeroVideo:"",questBarHero:""},features:[]},userStatus:{enrolledAt:"2099-01-01",claimedAt:null},benefits:{rewards:[]},guildId:"0",tasks:[]}}function tt(e){const t=e?.config?.assets;if(!t)return e;const n=t.questBarHero,o=t.questBarHeroVideo;return n!=null&&o!=null?e:{...e,config:{...e.config,assets:{...t,questBarHero:n??"",questBarHeroVideo:o??""}}}}function a(e){let t,n=!1;return function(){if(n)return t;const o=e();return o!=null&&(t=o,n=!0),o??void 0}}const H=a(function(){return T("useStateFromStores")}),V=a(function(){return U({triggerHapticFeedback:function(e){return typeof e=="function"},HapticFeedbackTypes:function(e){return e?.SOFT!==void 0}})}),ce=a(function(){return U({colors:function(e){return e?.BG_ACCENT!==void 0},unsafe_rawColors:function(e){return e?.WHITE!==void 0}})}),Re=a(function(){return T("bulkAck","ackChannel")}),De=a(function(){return U({ReadStateTypes:function(e){return e?.CHANNEL!==void 0},UnreadSetting:function(e){return e?.ALL_MESSAGES!==void 0}})});function Fe(e){if(e)try{let t=null;if(e._internalFiberInstanceHandleDEV)t=e._internalFiberInstanceHandleDEV;else if(e._internalInstanceHandle)t=e._internalInstanceHandle;else if(e.__internalInstanceHandle)t=e.__internalInstanceHandle;else{const l=Object.keys(e).find(function(s){return s.startsWith("__reactFiber$")||s.startsWith("__reactInternalInstance$")});l&&(t=e[l])}if(!t)return;if(t.return===void 0&&t.child===void 0){const l=t.stateNode??t.fiber??t._debugOwner;if(l&&(l.return!==void 0||l.child!==void 0))t=l;else return}let n=t,o=0;for(;n.return&&o<5e3;)n=n.return,o++;window.__serverDrawerFiberRoot=n,window.__serverDrawerFiberSelf=t}catch{}}const nt=a(function(){return b("GuildStore")});function Te({id:e,size:t=48}){const n=H(),o=nt(),l=ce()?.colors,s=n?.useStateFromStores?.([o],function(){return o?.getGuild?.(e)},[e])??null;if(!s)return null;const u=t>=40?16:8;return s.icon?r.createElement(i.Image,{source:{uri:`https://cdn.discordapp.com/icons/${s.id}/${s.icon}.png?size=${t*2}`},style:{width:t,height:t,borderRadius:u}}):r.createElement(i.View,{style:[xe.fallback,{width:t,height:t,borderRadius:u,backgroundColor:l?.BG_ACCENT??"#5865f2"}]},r.createElement(i.Text,{style:[xe.letter,{fontSize:Math.max(10,t*.4)}]},s.name?.split(" ").map(function(g){return g[0]}).join("").slice(0,2).toUpperCase()||"?"))}const xe=i.StyleSheet.create({fallback:{alignItems:"center",justifyContent:"center"},letter:{color:"#fff",fontWeight:"700"}}),rt=a(function(){return b("ThemeStore")}),ot=a(function(){return m(function(e){return e?.default?.internal?.resolveSemanticColor})?.default?.internal?.resolveSemanticColor??m(function(e){return e?.meta?.resolveSemanticColor})?.meta?.resolveSemanticColor});function it(e,t=rt()?.theme){if(e)try{return ot()?.(t,e)}catch{return}}const lt=a(function(){return U({TextStyleSheet:function(e){return e?.["text-md/bold"]!==void 0}})?.TextStyleSheet});function q(e,t){return it(e)??t}const x=12,de=12,Ae=42,fe=220,He=4,_=16,X=20,Ve={tension:200,friction:20};function st({visible:e,items:t,title:n,anchorX:o,anchorY:l,onClose:s}){const u=lt(),g=V(),{width:p,height:S}=i.Dimensions.get("window"),y=(n?de+20+He:0)+t.length*Ae;let d=o,w=l+48+10;d+fe>p-x&&(d=p-fe-x),dS-x&&(w=l-y-10),w0?r.createElement(i.View,{style:L.outline},r.createElement(i.View,{style:L.badge},r.createElement(i.Text,{style:L.text},o>99?"99+":String(o)))):l?r.createElement(i.View,{style:L.dotOutline},r.createElement(i.View,{style:L.dot})):null:null}function Pe({node:e,onPick:t}){const n=r.useRef(null),o=r.useRef(new i.Animated.Value(1)).current,l=function(){return i.Animated.spring(o,{toValue:.85,useNativeDriver:!0}).start()},s=function(){return i.Animated.spring(o,{toValue:1,useNativeDriver:!0}).start()},[u,g]=r.useState({visible:!1,items:[],title:"",x:0,y:0}),p=r.useCallback(function(){const d=e.id,w=dt()?.getGuild?.(d);if(!w)return;const B=n.current;if(!B?.measure)return;const A=[{label:"Mark as Read",action:function(){return gt(d)}},{label:"Copy Server ID",action:function(){c.clipboard.setString(d),I.showToast("Copied server ID",void 0)}}];B.measure(function(f,k,D,O,G,ne){g({visible:!0,items:A,title:w.name,x:G,y:ne})})},[e.id]),S=r.useCallback(function(){const d=V();d?.triggerHapticFeedback?.(d.HapticFeedbackTypes.IMPACT_MEDIUM),p()},[p]),y=e.id;return r.createElement(r.Fragment,null,r.createElement(i.Pressable,{onPressIn:l,onPressOut:s,onPress:function(){return t(y)},onLongPress:S,delayLongPress:500},r.createElement(i.View,{ref:n,style:Be.outer,collapsable:!1},r.createElement(i.Animated.View,{style:[Be.icon,{transform:[{scale:o}]}]},r.createElement(Te,{id:y})),r.createElement(pt,{guildId:y}))),r.createElement(st,{visible:u.visible,items:u.items,title:u.title,anchorX:u.x,anchorY:u.y,onClose:function(){return g(function(d){return{...d,visible:!1}})}}))}const Be=i.StyleSheet.create({outer:{width:J,height:J},icon:{width:J,height:J,borderRadius:16,overflow:"hidden"}}),L=i.StyleSheet.create({outline:{position:"absolute",bottom:-3,right:-3,minWidth:23,minHeight:23,borderRadius:12,backgroundColor:"#1a1a2e",alignItems:"center",justifyContent:"center"},badge:{minWidth:19,height:19,borderRadius:9,backgroundColor:"#ed4245",alignItems:"center",justifyContent:"center",paddingHorizontal:5},text:{color:"#fff",fontSize:10,fontWeight:"700",lineHeight:19},dotOutline:{position:"absolute",bottom:-2,right:-2,width:14,height:14,borderRadius:7,backgroundColor:"#1a1a2e",alignItems:"center",justifyContent:"center"},dot:{width:10,height:10,borderRadius:5,backgroundColor:"#ed4245"}}),mt=a(function(){return b("ExpandedGuildFolderStore")});function yt(e){const t=H(),n=mt();return t?.useStateFromStores?.([n],function(){const o=n?.getExpandedFolders?.();return o instanceof Set?o.has(e):!1},[e])??!1}const bt=a(function(){return T("toggleGuildFolderExpand")}),Ct=a(function(){return b("GuildReadStateStore")}),R=48,ge=16,wt=[{top:6,left:6},{top:6,right:6},{bottom:6,left:6},{bottom:6,right:6}],Ge=le.getAssetIDByName("FolderIcon");function ve(e){return e==null?"#5865f2":`#${e.toString(16).padStart(6,"0")}`}function Et({node:e}){const t=H(),n=Ct(),o=t?.useStateFromStores?.([n],function(){let l=0;for(const s of e.children)l+=n?.getMentionCount?.(s.id)??0;return l},[e.children])??0;return o>0?r.createElement(i.View,{style:me.outline},r.createElement(i.View,{style:me.badge},r.createElement(i.Text,{style:me.text},o>99?"99+":String(o)))):null}function St({node:e}){ie.useProxy(h.storage);const t=ve(e.color);return r.createElement(i.View,{style:Y.outer},r.createElement(i.View,{style:[Y.icon,{backgroundColor:t}]},h.storage.hideFolderIcons?r.createElement(i.View,{style:Y.plainIcon},r.createElement(i.Image,{source:Ge,style:pe.folderImg,tintColor:"#fff"})):e.children.slice(0,4).map(function(n,o){return r.createElement(i.View,{key:n.id,style:[Y.cell,wt[o]]},r.createElement(Te,{id:n.id,size:ge}))})),r.createElement(Et,{node:e}))}const Y=i.StyleSheet.create({outer:{width:R,height:R},icon:{width:R,height:R,borderRadius:16,overflow:"hidden"},cell:{position:"absolute",width:ge,height:ge,borderRadius:8,overflow:"hidden"},plainIcon:{width:R,height:R,alignItems:"center",justifyContent:"center"}});function kt({children:e}){const t=r.useRef(new i.Animated.Value(0)).current;return r.useEffect(function(){i.Animated.timing(t,{toValue:1,duration:180,useNativeDriver:!0}).start()},[]),r.createElement(i.Animated.View,{style:{opacity:t}},e)}function It({node:e,onPick:t}){const n=yt(e.id),o=function(){bt()?.toggleGuildFolderExpand?.(e.id)};return n?r.createElement(r.Fragment,null,r.createElement(i.Pressable,{onPress:o},r.createElement(i.View,{style:[pe.openIcon,{backgroundColor:ve(e.color)}]},r.createElement(i.Image,{source:Ge,style:pe.folderImg,tintColor:"#fff"}))),e.children.map(function(l){return r.createElement(kt,{key:l.id},r.createElement(Pe,{node:l,onPick:t}))})):r.createElement(i.Pressable,{onPress:o},r.createElement(St,{node:e}))}const pe=i.StyleSheet.create({openIcon:{width:R,height:R,borderRadius:16,alignItems:"center",justifyContent:"center"},folderImg:{width:24,height:24}}),me=i.StyleSheet.create({outline:{position:"absolute",bottom:-3,right:-3,minWidth:23,minHeight:23,borderRadius:12,backgroundColor:"#1a1a2e",alignItems:"center",justifyContent:"center"},badge:{minWidth:19,height:19,borderRadius:9,backgroundColor:"#ed4245",alignItems:"center",justifyContent:"center",paddingHorizontal:5},text:{color:"#fff",fontSize:10,fontWeight:"700",lineHeight:19}}),K=48,Rt=le.getAssetIDByName("ChatIcon"),Dt=a(function(){return T("selectPrivateChannel")}),Ft=a(function(){return Xe("SelectedChannelStore")}),Tt=a(function(){return T("getGuildId")});function xt(){const e=V();e?.triggerHapticFeedback?.(e.HapticFeedbackTypes.SOFT);const t=Dt();if(t?.selectPrivateChannel){const n=Ft()?.getLastSelectedChannelId?.();t.selectPrivateChannel(n)}}function At(){const e=H(),t=Tt(),n=ce()?.colors,o=e?.useStateFromStores?.([t],function(){return t?.getGuildId?.()==null})??!1;return r.createElement(i.Pressable,{onPress:xt,style:_e.outer},r.createElement(i.View,{style:[_e.icon,{backgroundColor:o?n?.BG_ACCENT??"#5865f2":"rgba(128,128,128,0.24)"}]},r.createElement(i.Image,{source:Rt,style:{width:24,height:24,tintColor:"#fff"}})))}const _e=i.StyleSheet.create({outer:{width:K,height:K},icon:{width:K,height:K,borderRadius:16,alignItems:"center",justifyContent:"center"}}),Le=48,Ht=le.getAssetIDByName("CheckmarkLargeIcon"),Vt=Re,Pt=a(function(){return De()?.ReadStateTypes}),Bt=a(function(){return b("SortedGuildStore")}),Gt=a(function(){return b("GuildChannelStore")}),vt=a(function(){return b("ChannelStore")});function _t(){const e=(Bt()?.getGuildsTree?.()?.root?.children??[]).filter(function(o){return o?.type!=="root"}),t=[],n=function(o){for(const l of o)l.type==="folder"?n(l.children??[]):l.id!=null&&t.push(String(l.id))};return n(e),t}function Lt(){const e=Vt(),t=Pt(),n=Gt(),o=vt();if(!e?.bulkAck||t?.CHANNEL==null||!n?.getSelectableChannelIds||!n?.getVocalChannelIds){I.showToast("Couldn't find Discord's read-state action - this may be unavailable on your version.",void 0);return}const l=_t();if(l.length===0){I.showToast("Nothing to mark as read.",void 0);return}const s=[];for(const u of l){const g=[...n.getSelectableChannelIds(u)??[],...n.getVocalChannelIds(u)??[]];for(const p of g)s.push({channelId:p,readStateType:t.CHANNEL,messageId:o?.getChannel?.(p)?.lastMessageId??null})}if(s.length===0){I.showToast("Nothing to mark as read.",void 0);return}e.bulkAck(s),I.showToast(`Marked ${s.length} channel${s.length===1?"":"s"} as read`,void 0)}function jt(){const e=r.useCallback(function(){const t=V();t?.triggerHapticFeedback?.(t.HapticFeedbackTypes.SOFT),Lt()},[]);return r.createElement(i.Pressable,{onPress:e,style:Ot.outer},r.createElement(i.Image,{source:Ht,style:{width:24,height:24,tintColor:"#80848e"}}))}const Ot=i.StyleSheet.create({outer:{width:Le,height:Le,alignItems:"center",justifyContent:"center"}}),Mt=a(function(){return T("getRootNavigationRef")}),zt=a(function(){return T("transitionToGuild")}),Ut=a(function(){return m(function(e){return typeof e?.handleCreateJoinGuildPress=="function"})}),Wt=a(function(){return m(function(e){return e?.CirclePlusIcon})?.CirclePlusIcon}),Qt=a(function(){return m(function(e){return e?.QuestDockExternalCoordinationContext})?.QuestDockExternalCoordinationContext}),qt=a(function(){return m(function(e){return e?.QuestDockMode?.COLLAPSED!=null})?.QuestDockMode}),Xt=a(function(){return m(function(e){return typeof e?.getName=="function"&&e.getName.length===0&&e.getName()==="SortedGuildStore"})}),Z=48,$=6,Jt=12;function Yt(){const e=r.useRef(new i.Animated.Value(1)).current,t=r.useCallback(function(){i.Animated.spring(e,{toValue:.9,useNativeDriver:!0}).start()},[e]),n=r.useCallback(function(){i.Animated.spring(e,{toValue:1,useNativeDriver:!0}).start()},[e]),o=r.useCallback(function(){const u=V();u?.triggerHapticFeedback?.(u.HapticFeedbackTypes.SOFT),Ut()?.handleCreateJoinGuildPress?.()},[]),l=Wt(),s=ce()?.unsafe_rawColors;return r.createElement(i.Pressable,{onPress:o,onPressIn:t,onPressOut:n},r.createElement(i.Animated.View,{style:[N.createJoin,{backgroundColor:s?.GREEN_360,transform:[{scale:e}]}]},l?r.createElement(l,{size:"md",color:s?.WHITE}):r.createElement(i.Text,{style:[N.createJoinFallback,{color:s?.WHITE}]},"+")))}function Kt({gestureContext:e}){const t=r.useCallback(function(f){const k=V();k?.triggerHapticFeedback?.(k.HapticFeedbackTypes.SOFT);const D=zt();D?.transitionToGuild?D.transitionToGuild(f):Mt()?.getRootNavigationRef?.()?.navigate("guilds",{guildId:f})},[]),n=H(),o=Xt(),l=n?.useStateFromStores?.([o],function(){return(o?.getGuildsTree()?.root?.children||[]).filter(function(f){return f.type!=="root"})})??[],s=e?r.useContext(e):null,u=s?.minExpandedContentHeight,g=r.useCallback(function(f){if(!u)return;const k=f.nativeEvent.layout.height;u.get()!==k&&u.set(k)},[u]),p=Qt(),S=(p?r.useContext(p):null)?.setRestingQuestDockMode,y=s?.questDockWrapperSpecs;r.useEffect(function(){const f=qt();if(!S||!f||!y)return;const k=i.BackHandler.addEventListener("hardwareBackPress",function(){return(y.get()?.height??56)>80?(S(f.COLLAPSED),!0):!1});return function(){return k.remove()}},[S,y]);const{width:d}=i.Dimensions.get("window"),w=Math.max(3,Math.floor((d-Jt*2+$)/(Z+$))),B=w*Z+(w-1)*$,A=Math.max(0,(d-B)/2);return r.createElement(i.View,{style:N.alignTop},r.createElement(i.View,{ref:Fe,style:{width:1,height:1}}),r.createElement(i.View,{style:[N.grid,{paddingHorizontal:A,gap:$}],onLayout:g},r.createElement(At,null),l.map(function(f){return f.type==="folder"?r.createElement(It,{key:f.id,node:f,onPick:t}):r.createElement(Pe,{key:f.id,node:f,onPick:t})}),r.createElement(Yt,null),r.createElement(jt,null)))}const N=i.StyleSheet.create({alignTop:{flex:1,justifyContent:"flex-start",alignItems:"flex-start"},grid:{flexDirection:"row",flexWrap:"wrap",paddingTop:4,paddingBottom:16},createJoin:{width:Z,height:Z,borderRadius:16,alignItems:"center",justifyContent:"center"},createJoinFallback:{fontSize:28,fontWeight:"700",lineHeight:30}}),P="[ServerDrawer]";let ye=null;function Zt(){return ye||(ye=m(function(e){return e?.QuestDockGestureContext})?.QuestDockGestureContext??null),ye}function ee(e){return function(t){return t?.name===e||t?.displayName===e||t?.type?.name===e||t?.type?.displayName===e}}function be(){return c.React.createElement(Kt,{gestureContext:Zt()})}function $t(e){ae(ee("QuestDockContentExpanded"),function(o){Q(o,be),console.log(P,"PATCH: QuestDockContentExpanded replaced (type detector)")});const t=m(function(o){return ee("QuestDockContentExpanded")(o?.type)});if(!t?.type)return console.log(P,"WARN: QuestDockContentExpanded module not found yet (will retry)"),!1;const n=t.type;return Q(n,be),t.type=be,e.push(function(){t.type=n}),console.log(P,"PATCH: QuestDockContentExpanded replaced (module mutation)"),!0}function j(e,t){ae(ee(e),function(s){Q(s,function(){return null}),console.log(P,`PATCH: ${e} replaced (type detector)`)});const n=m(function(s){return ee(e)(s?.type)});if(!n?.type)return console.log(P,`WARN: ${e} module not found yet (will retry)`),!1;const o=n.type;function l(){return null}n.type=l;try{Object.defineProperties(n.type,Object.getOwnPropertyDescriptors(o))}catch{}return n.type.displayName=e,t.push(function(){n.type=o}),console.log(P,`PATCH: ${e} replaced (module mutation)`),!0}const je="[ServerDrawer]";function Nt(){return r.createElement(i.View,{ref:Fe,style:{width:1,height:1}})}function en(e){return e?.name==="GuildsBar"||e?.displayName==="GuildsBar"||e?.type?.name==="GuildsBar"||e?.type?.displayName==="GuildsBar"}function tn(e){return ae(en,function(t){Q(t,Nt),console.log(je,"PATCH: found a real GuildsBar reference, now rendering nothing")},{persistent:!0}),e.push(function(){}),console.log(je,"PATCH: watching for the real GuildsBar to appear"),!0}function nn(e){const t=b("ExpandedGuildFolderStore");if(!t?.getExpandedFolders)return!1;const n=function({folderId:o}){if(!h.storage.autoCollapseFolders||o==null)return;const l=t.getExpandedFolders();if(!(!(l instanceof Set)||!l.has(o)))for(const s of l)s!==o&&c.FluxDispatcher.dispatch({type:"TOGGLE_GUILD_FOLDER_EXPAND",folderId:s})};return c.FluxDispatcher.subscribe("TOGGLE_GUILD_FOLDER_EXPAND",n),e.push(function(){return c.FluxDispatcher.unsubscribe("TOGGLE_GUILD_FOLDER_EXPAND",n)}),!0}const{ScrollView:rn,View:on}=c.ReactNative;function ln({children:e}){return c.React.createElement(rn,{style:{flex:1}},e,c.React.createElement(on,{style:{height:24}}))}const{View:sn,Text:un}=c.ReactNative;function Oe({children:e,style:t}){return c.React.createElement(sn,{style:[{marginHorizontal:16,marginVertical:8,padding:10,borderRadius:8,borderWidth:1,borderColor:"rgba(128,128,128,0.25)"},t]},c.React.createElement(un,{style:{fontSize:12.5,lineHeight:18,opacity:.75}},e))}const{FormSection:Me,FormSwitchRow:te}=qe.Forms;function an(){return ie.useProxy(h.storage),c.React.createElement(ln,null,c.React.createElement(Oe,null,"Server Drawer takes over the Quest Dock (the strip above the tab bar) to show your servers as a grid instead - tap to expand, long-press a server for its usual context menu, the chat bubble jumps to DMs, the + button creates or joins a server through Discord's own modal, and the check button marks every channel in every server as read."),c.React.createElement(Me,{title:"Layout"},c.React.createElement(te,{label:"Hide the left server rail",subLabel:"Your servers and DMs already live in the drawer, so the rail is redundant",value:h.storage.hideGuildsBar!==!1,onValueChange:function(e){h.storage.hideGuildsBar=e,We()}}),c.React.createElement(te,{label:"Unread badges",subLabel:"Show mention counts and unread dots on server icons in the drawer",value:h.storage.showUnreadBadges!==!1,onValueChange:function(e){h.storage.showUnreadBadges=e}})),c.React.createElement(Me,{title:"Folders"},c.React.createElement(te,{label:"Auto-collapse other folders",subLabel:"Opening a folder collapses any other folder that was already open",value:!!h.storage.autoCollapseFolders,onValueChange:function(e){h.storage.autoCollapseFolders=e}}),c.React.createElement(te,{label:"Hide icons in collapsed folders",subLabel:"Show a plain folder icon instead of a 4-server preview",value:!!h.storage.hideFolderIcons,onValueChange:function(e){h.storage.hideFolderIcons=e}})),c.React.createElement(Oe,null,"The folder options above are ported from fres621's BetterFolders - its other half (hiding icons in the native left server rail) patched a component that no longer exists in current Discord builds, so it's been rebuilt here instead, where it actually applies to what you see."))}let C=[],E;function cn(e,t){try{return t()}catch(n){return oe.logger.error(`[ServerDrawer] "${e}" patch threw, skipping: ${n}`),!1}}function ze(){const e={questDockContext:function(){return Ne(C)},expanded:function(){return $t(C)},collapsed:function(){return j("QuestDockContentCollapsed",C)},enrolledHeader:function(){return j("QuestDockEnrolledHeader",C)},unenrolledHeader:function(){return j("QuestDockUnenrolledHeader",C)},enrolledBody:function(){return j("QuestDockEnrolledBody",C)},unenrolledBody:function(){return j("QuestDockUnenrolledBody",C)},autoCollapseFolders:function(){return nn(C)},...h.storage.hideGuildsBar?{hideGuildsBar:function(){return tn(C)}}:{}};Ze(C);const t=new Set(Object.keys(e)),n=new Set,o=function(){for(const l of t)cn(l,e[l])&&(n.add(l),t.delete(l));t.size===0&&E&&(clearInterval(E),E=void 0)};if(o(),t.size>0){let l=0;E=setInterval(function(){o(),++l>=50&&E&&(clearInterval(E),E=void 0,t.size>0&&oe.logger.error(`[ServerDrawer] Gave up waiting on: ${[...t].join(", ")}`))},200)}oe.logger.log(`[ServerDrawer] onLoad: applied immediately - ${[...n].join(", ")||"none"}${t.size?`, still waiting on ${[...t].join(", ")}`:""}`)}function Ue(){E&&(clearInterval(E),E=void 0);for(const e of C)try{e()}catch{}C=[]}function We(){Ue(),ze()}var dn={onLoad:function(){h.storage.hideGuildsBar??=!0,h.storage.showUnreadBadges??=!0,h.storage.autoCollapseFolders??=!1,h.storage.hideFolderIcons??=!1,ze()},onUnload:function(){return Ue()},settings:an};return M.default=dn,M.restart=We,Object.defineProperty(M,"__esModule",{value:!0}),M})({},vendetta,vendetta.plugin,vendetta.metro.common,window.React,vendetta.metro.common.ReactNative,vendetta.storage,vendetta.ui.toasts,vendetta.ui,vendetta.ui.assets,vendetta.ui.components); +(function(U,le,c,d,r,i,L,I,Q,se,Xe){"use strict";function p(e){const t=window?.modules;if(t)for(const n in t){const o=t[n];if(!o?.isInitialized)continue;const l=o.publicModule?.exports;if(l)try{if(e(l))return l;if(l.default!=null&&e(l.default))return l.default}catch{}}}function Je(e){return p(function(t){return t?.name===e||t?.displayName===e})}function x(...e){return p(function(t){return e.every(function(n){return typeof t?.[n]=="function"})})}function q(e){const t=Object.keys(e);return p(function(n){return t.every(function(o){try{return e[o](n?.[o])}catch{return!1}})})}function b(e){return p(function(t){return typeof t?.getName=="function"&&t.getName.length===0&&t.getName()===e})}function Ye(e,t,n=100){let o=!1,l;const s=e();return s?(t(s),{cancel(){}}):(l=setInterval(function(){if(o)return;const a=e();a&&(o=!0,clearInterval(l),t(a))},n),{cancel(){o=!0,l&&clearInterval(l)}})}const ae=new Map,Ie=[],ue=[];let O=[],X=!1;function J(e,t,n){ae.set(e,{replacement:t,extraProps:n})}function Ke(e,t){ue.push({predicate:e,transform:t})}function ce(e,t,n){O.push({predicate:e,onDetected:t,persistent:n?.persistent??!1})}function Ze(e){if(O.length===0)return;const t=[];for(const n of O){let o=!1;try{o=n.predicate(e)}catch{}if(o){try{n.onDetected(e)}catch{}n.persistent&&t.push(n)}else t.push(n)}O=t}function Re(e,t){Ze(e);let n=t;if(n)for(const{predicate:l,transform:s}of ue)try{l(n)&&(n=s(n))}catch{}if(n)for(const{predicate:l,replacement:s}of Ie)try{if(l(n))return s?{type:s,props:n}:null}catch{}const o=ae.get(e);if(o)return{type:o.replacement,props:o.extraProps?{...n,...o.extraProps}:n};if(n!==t)return{type:e,props:n}}function $e(e){if(X)return;const t=d.React.createElement;if(!t){console.warn("[ServerDrawer] React.createElement is null, skipping patch");return}const n=function(s,a,...g){const m=Re(s,a);return m===null?null:m?t.call(d.React,m.type,m.props,...g):t.call(d.React,s,a,...g)};Object.assign(n,t),d.React.createElement=n,X=!0;const o=[],l=Ye(function(){return p(function(s){return typeof s?.jsx=="function"&&typeof s?.jsxs=="function"&&"Fragment"in s})},function(s){for(const a of["jsx","jsxs"]){const g=s[a];typeof g=="function"&&(s[a]=function(m,S,...y){const f=Re(m,S);return f===null?null:f?g.call(this,f.type,f.props,...y):g.call(this,m,S,...y)},o.push(function(){s[a]=g}))}});e.push(function(){l.cancel(),X&&(d.React.createElement=t,X=!1),o.forEach(function(s){return s()}),ae.clear(),Ie.length=0,ue.length=0,O=[]})}const Ne="[ServerDrawer]";function et(e){return Ke(function(t){const n=t?.value;return!!(n&&typeof n=="object"&&"isRendered"in n&&"isVisibleToUser"in n&&"quest"in n)},function(t){const n=t.value,o=n.quest??tt();return{...t,value:{...n,isRendered:!0,isVisibleToUser:!0,quest:nt(o)}}}),e.push(function(){}),console.log(Ne,"PATCH: watching for the Quest Dock coordination context"),!0}function tt(){return{id:"server-drawer",config:{quest_content_type:0,assets:{questBarHeroVideo:"",questBarHero:""},features:[]},userStatus:{enrolledAt:"2099-01-01",claimedAt:null},benefits:{rewards:[]},guildId:"0",tasks:[]}}function nt(e){const t=e?.config?.assets;if(!t)return e;const n=t.questBarHero,o=t.questBarHeroVideo;return n!=null&&o!=null?e:{...e,config:{...e.config,assets:{...t,questBarHero:n??"",questBarHeroVideo:o??""}}}}function u(e){let t,n=!1;return function(){if(n)return t;const o=e();return o!=null&&(t=o,n=!0),o??void 0}}const F=u(function(){return x("useStateFromStores")}),H=u(function(){return q({triggerHapticFeedback:function(e){return typeof e=="function"},HapticFeedbackTypes:function(e){return e?.SOFT!==void 0}})}),Y=u(function(){return q({colors:function(e){return e?.BG_ACCENT!==void 0},unsafe_rawColors:function(e){return e?.WHITE!==void 0}})}),Te=u(function(){return x("bulkAck","ackChannel")}),De=u(function(){return q({ReadStateTypes:function(e){return e?.CHANNEL!==void 0},UnreadSetting:function(e){return e?.ALL_MESSAGES!==void 0}})});function xe(e){if(e)try{let t=null;if(e._internalFiberInstanceHandleDEV)t=e._internalFiberInstanceHandleDEV;else if(e._internalInstanceHandle)t=e._internalInstanceHandle;else if(e.__internalInstanceHandle)t=e.__internalInstanceHandle;else{const l=Object.keys(e).find(function(s){return s.startsWith("__reactFiber$")||s.startsWith("__reactInternalInstance$")});l&&(t=e[l])}if(!t)return;if(t.return===void 0&&t.child===void 0){const l=t.stateNode??t.fiber??t._debugOwner;if(l&&(l.return!==void 0||l.child!==void 0))t=l;else return}let n=t,o=0;for(;n.return&&o<5e3;)n=n.return,o++;window.__serverDrawerFiberRoot=n,window.__serverDrawerFiberSelf=t}catch{}}const rt=u(function(){return b("ExpandedGuildFolderStore")});function ot(){const e=Y()?.colors;return{text:e?.TEXT_NORMAL??"#dbdee1",folder:"#5865f2",hover:e?.STATE_LAYER_PRESS??"rgba(255,255,255,0.06)"}}function it(e){const t=F(),n=rt();return t?.useStateFromStores?.([n],function(){const o=n?.getExpandedFolders?.();return o instanceof Set?o.has(e):!1},[e])??!1}const lt=u(function(){return b("GuildStore")});function Fe({id:e,size:t=48}){const n=F(),o=lt(),l=Y()?.colors,s=n?.useStateFromStores?.([o],function(){return o?.getGuild?.(e)},[e])??null;if(!s)return null;const a=t>=40?16:8;return s.icon?r.createElement(i.Image,{source:{uri:`https://cdn.discordapp.com/icons/${s.id}/${s.icon}.png?size=${t*2}`},style:{width:t,height:t,borderRadius:a}}):r.createElement(i.View,{style:[Ae.fallback,{width:t,height:t,borderRadius:a,backgroundColor:l?.BG_ACCENT??"#5865f2"}]},r.createElement(i.Text,{style:[Ae.letter,{fontSize:Math.max(10,t*.4)}]},s.name?.split(" ").map(function(g){return g[0]}).join("").slice(0,2).toUpperCase()||"?"))}const Ae=i.StyleSheet.create({fallback:{alignItems:"center",justifyContent:"center"},letter:{color:"#fff",fontWeight:"700"}}),st=u(function(){return b("ThemeStore")}),at=u(function(){return p(function(e){return e?.default?.internal?.resolveSemanticColor})?.default?.internal?.resolveSemanticColor??p(function(e){return e?.meta?.resolveSemanticColor})?.meta?.resolveSemanticColor});function ut(e,t=st()?.theme){if(e)try{return at()?.(t,e)}catch{return}}const ct=u(function(){return q({TextStyleSheet:function(e){return e?.["text-md/bold"]!==void 0}})?.TextStyleSheet});function K(e,t){return ut(e)??t}const A=12,de=12,Ve=42,fe=220,He=4,M=16,Z=20,Pe={tension:200,friction:20};function dt({visible:e,items:t,title:n,anchorX:o,anchorY:l,onClose:s}){const a=ct(),g=H(),{width:m,height:S}=i.Dimensions.get("window"),y=(n?de+20+He:0)+t.length*Ve;let f=o,w=l+48+10;f+fe>m-A&&(f=m-fe-A),fS-A&&(w=l-y-10),w0?r.createElement(i.View,{style:j.outline},r.createElement(i.View,{style:j.badge},r.createElement(i.Text,{style:j.text},o>99?"99+":String(o)))):l?r.createElement(i.View,{style:j.dotOutline},r.createElement(i.View,{style:j.dot})):null:null}function Ct({guildId:e}){L.useProxy(c.storage);const t=ot(),n=F(),o=Ge(),l=n?.useStateFromStores?.([o],function(){return o?.getGuild?.(e)?.name??""},[e])??"";return c.storage.showGuildNames===!1||!l?null:r.createElement(i.Text,{numberOfLines:2,style:[wt.label,{color:t.text}]},l)}function ve({node:e,onPick:t}){const n=r.useRef(null),o=r.useRef(new i.Animated.Value(1)).current,l=function(){return i.Animated.spring(o,{toValue:.85,useNativeDriver:!0}).start()},s=function(){return i.Animated.spring(o,{toValue:1,useNativeDriver:!0}).start()},[a,g]=r.useState({visible:!1,items:[],title:"",x:0,y:0}),m=r.useCallback(function(){const f=e.id,w=Ge()?.getGuild?.(f);if(!w)return;const B=n.current;if(!B?.measure)return;const V=[{label:"Mark as Read",action:function(){return yt(f)}},{label:"Copy Server ID",action:function(){d.clipboard.setString(f),I.showToast("Copied server ID",void 0)}}];B.measure(function(h,k,T,W,_,oe){g({visible:!0,items:V,title:w.name,x:_,y:oe})})},[e.id]),S=r.useCallback(function(){const f=H();f?.triggerHapticFeedback?.(f.HapticFeedbackTypes.IMPACT_MEDIUM),m()},[m]),y=e.id;return r.createElement(r.Fragment,null,r.createElement(i.Pressable,{onPressIn:l,onPressOut:s,onPress:function(){return t(y)},onLongPress:S,delayLongPress:500},r.createElement(i.View,{style:ge.outer},r.createElement(i.View,{ref:n,style:ge.iconWrap,collapsable:!1},r.createElement(i.Animated.View,{style:[ge.icon,{transform:[{scale:o}]}]},r.createElement(Fe,{id:y})),r.createElement(bt,{guildId:y})),r.createElement(Ct,{guildId:y}))),r.createElement(dt,{visible:a.visible,items:a.items,title:a.title,anchorX:a.x,anchorY:a.y,onClose:function(){return g(function(f){return{...f,visible:!1}})}}))}const ge=i.StyleSheet.create({outer:{width:P},iconWrap:{width:P,height:P},icon:{width:P,height:P,borderRadius:16,overflow:"hidden"}}),wt=i.StyleSheet.create({label:{width:P,marginTop:4,fontSize:10,lineHeight:12,textAlign:"center"}}),j=i.StyleSheet.create({outline:{position:"absolute",bottom:-3,right:-3,minWidth:23,minHeight:23,borderRadius:12,backgroundColor:"#1a1a2e",alignItems:"center",justifyContent:"center"},badge:{minWidth:19,height:19,borderRadius:9,backgroundColor:"#ed4245",alignItems:"center",justifyContent:"center",paddingHorizontal:5},text:{color:"#fff",fontSize:10,fontWeight:"700",lineHeight:19},dotOutline:{position:"absolute",bottom:-2,right:-2,width:14,height:14,borderRadius:7,backgroundColor:"#1a1a2e",alignItems:"center",justifyContent:"center"},dot:{width:10,height:10,borderRadius:5,backgroundColor:"#ed4245"}}),Et=u(function(){return x("toggleGuildFolderExpand")}),St=u(function(){return b("GuildReadStateStore")}),R=48,me=16,kt=[{top:6,left:6},{top:6,right:6},{bottom:6,left:6},{bottom:6,right:6}],Be=se.getAssetIDByName("FolderIcon");function _e(e){return e==null?"#5865f2":`#${e.toString(16).padStart(6,"0")}`}function It({node:e}){const t=F(),n=St(),o=t?.useStateFromStores?.([n],function(){let l=0;for(const s of e.children)l+=n?.getMentionCount?.(s.id)??0;return l},[e.children])??0;return o>0?r.createElement(i.View,{style:ye.outline},r.createElement(i.View,{style:ye.badge},r.createElement(i.Text,{style:ye.text},o>99?"99+":String(o)))):null}function Rt({node:e}){L.useProxy(c.storage);const t=_e(e.color);return r.createElement(i.View,{style:$.outer},r.createElement(i.View,{style:[$.icon,{backgroundColor:t}]},c.storage.hideFolderIcons?r.createElement(i.View,{style:$.plainIcon},r.createElement(i.Image,{source:Be,style:pe.folderImg,tintColor:"#fff"})):e.children.slice(0,4).map(function(n,o){return r.createElement(i.View,{key:n.id,style:[$.cell,kt[o]]},r.createElement(Fe,{id:n.id,size:me}))})),r.createElement(It,{node:e}))}const $=i.StyleSheet.create({outer:{width:R,height:R},icon:{width:R,height:R,borderRadius:16,overflow:"hidden"},cell:{position:"absolute",width:me,height:me,borderRadius:8,overflow:"hidden"},plainIcon:{width:R,height:R,alignItems:"center",justifyContent:"center"}});function Tt({children:e}){const t=r.useRef(new i.Animated.Value(0)).current;return r.useEffect(function(){i.Animated.timing(t,{toValue:1,duration:180,useNativeDriver:!0}).start()},[]),r.createElement(i.Animated.View,{style:{opacity:t}},e)}function Dt({node:e,onPick:t}){const n=it(e.id),o=function(){Et()?.toggleGuildFolderExpand?.(e.id)};return n?r.createElement(r.Fragment,null,r.createElement(i.Pressable,{onPress:o},r.createElement(i.View,{style:[pe.openIcon,{backgroundColor:_e(e.color)}]},r.createElement(i.Image,{source:Be,style:pe.folderImg,tintColor:"#fff"}))),e.children.map(function(l){return r.createElement(Tt,{key:l.id},r.createElement(ve,{node:l,onPick:t}))})):r.createElement(i.Pressable,{onPress:o},r.createElement(Rt,{node:e}))}const pe=i.StyleSheet.create({openIcon:{width:R,height:R,borderRadius:16,alignItems:"center",justifyContent:"center"},folderImg:{width:24,height:24}}),ye=i.StyleSheet.create({outline:{position:"absolute",bottom:-3,right:-3,minWidth:23,minHeight:23,borderRadius:12,backgroundColor:"#1a1a2e",alignItems:"center",justifyContent:"center"},badge:{minWidth:19,height:19,borderRadius:9,backgroundColor:"#ed4245",alignItems:"center",justifyContent:"center",paddingHorizontal:5},text:{color:"#fff",fontSize:10,fontWeight:"700",lineHeight:19}}),N=48,xt=se.getAssetIDByName("ChatIcon"),Ft=u(function(){return x("selectPrivateChannel")}),At=u(function(){return Je("SelectedChannelStore")}),Vt=u(function(){return x("getGuildId")});function Ht(){const e=H();e?.triggerHapticFeedback?.(e.HapticFeedbackTypes.SOFT);const t=Ft();if(t?.selectPrivateChannel){const n=At()?.getLastSelectedChannelId?.();t.selectPrivateChannel(n)}}function Pt(){const e=F(),t=Vt(),n=Y()?.colors,o=e?.useStateFromStores?.([t],function(){return t?.getGuildId?.()==null})??!1;return r.createElement(i.Pressable,{onPress:Ht,style:Le.outer},r.createElement(i.View,{style:[Le.icon,{backgroundColor:o?n?.BG_ACCENT??"#5865f2":"rgba(128,128,128,0.24)"}]},r.createElement(i.Image,{source:xt,style:{width:24,height:24,tintColor:"#fff"}})))}const Le=i.StyleSheet.create({outer:{width:N,height:N},icon:{width:N,height:N,borderRadius:16,alignItems:"center",justifyContent:"center"}}),Oe=48,Gt=se.getAssetIDByName("CheckmarkLargeIcon"),vt=Te,Bt=u(function(){return De()?.ReadStateTypes}),_t=u(function(){return b("SortedGuildStore")}),Lt=u(function(){return b("GuildChannelStore")}),Ot=u(function(){return b("ChannelStore")});function Mt(){const e=(_t()?.getGuildsTree?.()?.root?.children??[]).filter(function(o){return o?.type!=="root"}),t=[],n=function(o){for(const l of o)l.type==="folder"?n(l.children??[]):l.id!=null&&t.push(String(l.id))};return n(e),t}function jt(){const e=vt(),t=Bt(),n=Lt(),o=Ot();if(!e?.bulkAck||t?.CHANNEL==null||!n?.getSelectableChannelIds||!n?.getVocalChannelIds){I.showToast("Couldn't find Discord's read-state action - this may be unavailable on your version.",void 0);return}const l=Mt();if(l.length===0){I.showToast("Nothing to mark as read.",void 0);return}const s=[];for(const a of l){const g=[...n.getSelectableChannelIds(a)??[],...n.getVocalChannelIds(a)??[]];for(const m of g)s.push({channelId:m,readStateType:t.CHANNEL,messageId:o?.getChannel?.(m)?.lastMessageId??null})}if(s.length===0){I.showToast("Nothing to mark as read.",void 0);return}e.bulkAck(s),I.showToast(`Marked ${s.length} channel${s.length===1?"":"s"} as read`,void 0)}function zt(){const e=r.useCallback(function(){const t=H();t?.triggerHapticFeedback?.(t.HapticFeedbackTypes.SOFT),jt()},[]);return r.createElement(i.Pressable,{onPress:e,style:Wt.outer},r.createElement(i.Image,{source:Gt,style:{width:24,height:24,tintColor:"#80848e"}}))}const Wt=i.StyleSheet.create({outer:{width:Oe,height:Oe,alignItems:"center",justifyContent:"center"}}),Ut=u(function(){return x("getRootNavigationRef")}),Qt=u(function(){return x("transitionToGuild")}),qt=u(function(){return p(function(e){return typeof e?.handleCreateJoinGuildPress=="function"})}),Xt=u(function(){return p(function(e){return e?.CirclePlusIcon})?.CirclePlusIcon}),Jt=u(function(){return p(function(e){return e?.QuestDockExternalCoordinationContext})?.QuestDockExternalCoordinationContext}),Yt=u(function(){return p(function(e){return e?.QuestDockMode?.COLLAPSED!=null})?.QuestDockMode}),Kt=u(function(){return p(function(e){return typeof e?.getName=="function"&&e.getName.length===0&&e.getName()==="SortedGuildStore"})}),ee=48,te=6,Zt=12;function $t(){const e=r.useRef(new i.Animated.Value(1)).current,t=r.useCallback(function(){i.Animated.spring(e,{toValue:.9,useNativeDriver:!0}).start()},[e]),n=r.useCallback(function(){i.Animated.spring(e,{toValue:1,useNativeDriver:!0}).start()},[e]),o=r.useCallback(function(){const a=H();a?.triggerHapticFeedback?.(a.HapticFeedbackTypes.SOFT),qt()?.handleCreateJoinGuildPress?.()},[]),l=Xt(),s=Y()?.unsafe_rawColors;return r.createElement(i.Pressable,{onPress:o,onPressIn:t,onPressOut:n},r.createElement(i.Animated.View,{style:[ne.createJoin,{backgroundColor:s?.GREEN_360,transform:[{scale:e}]}]},l?r.createElement(l,{size:"md",color:s?.WHITE}):r.createElement(i.Text,{style:[ne.createJoinFallback,{color:s?.WHITE}]},"+")))}function Nt({gestureContext:e}){L.useProxy(c.storage);const t=r.useCallback(function(h){const k=H();k?.triggerHapticFeedback?.(k.HapticFeedbackTypes.SOFT);const T=Qt();T?.transitionToGuild?T.transitionToGuild(h):Ut()?.getRootNavigationRef?.()?.navigate("guilds",{guildId:h})},[]),n=F(),o=Kt(),l=n?.useStateFromStores?.([o],function(){return(o?.getGuildsTree()?.root?.children||[]).filter(function(h){return h.type!=="root"})})??[],s=e?r.useContext(e):null,a=s?.minExpandedContentHeight,g=r.useCallback(function(h){if(!a)return;const k=h.nativeEvent.layout.height;a.get()!==k&&a.set(k)},[a]),m=Jt(),S=(m?r.useContext(m):null)?.setRestingQuestDockMode,y=s?.questDockWrapperSpecs;r.useEffect(function(){const h=Yt();if(!S||!h||!y)return;const k=i.BackHandler.addEventListener("hardwareBackPress",function(){return(y.get()?.height??56)>80?(S(h.COLLAPSED),!0):!1});return function(){return k.remove()}},[S,y]);const{width:f}=i.Dimensions.get("window"),w=Math.max(3,Math.floor((f-Zt*2+te)/(ee+te))),B=w*ee+(w-1)*te,V=Math.max(0,(f-B)/2);return r.createElement(i.View,{style:ne.alignTop},r.createElement(i.View,{ref:xe,style:{width:1,height:1}}),r.createElement(i.View,{style:[ne.grid,{paddingHorizontal:V,gap:te}],onLayout:g},!c.storage.hideDmTile&&r.createElement(Pt,null),l.map(function(h){return h.type==="folder"?r.createElement(Dt,{key:h.id,node:h,onPick:t}):r.createElement(ve,{key:h.id,node:h,onPick:t})}),r.createElement($t,null),r.createElement(zt,null)))}const ne=i.StyleSheet.create({alignTop:{flex:1,justifyContent:"flex-start",alignItems:"flex-start"},grid:{flexDirection:"row",flexWrap:"wrap",paddingTop:4,paddingBottom:16},createJoin:{width:ee,height:ee,borderRadius:16,alignItems:"center",justifyContent:"center"},createJoinFallback:{fontSize:28,fontWeight:"700",lineHeight:30}}),G="[ServerDrawer]";let be=null;function en(){return be||(be=p(function(e){return e?.QuestDockGestureContext})?.QuestDockGestureContext??null),be}function re(e){return function(t){return t?.name===e||t?.displayName===e||t?.type?.name===e||t?.type?.displayName===e}}function Ce(){return d.React.createElement(Nt,{gestureContext:en()})}function tn(e){ce(re("QuestDockContentExpanded"),function(o){J(o,Ce),console.log(G,"PATCH: QuestDockContentExpanded replaced (type detector)")});const t=p(function(o){return re("QuestDockContentExpanded")(o?.type)});if(!t?.type)return console.log(G,"WARN: QuestDockContentExpanded module not found yet (will retry)"),!1;const n=t.type;return J(n,Ce),t.type=Ce,e.push(function(){t.type=n}),console.log(G,"PATCH: QuestDockContentExpanded replaced (module mutation)"),!0}function z(e,t){ce(re(e),function(s){J(s,function(){return null}),console.log(G,`PATCH: ${e} replaced (type detector)`)});const n=p(function(s){return re(e)(s?.type)});if(!n?.type)return console.log(G,`WARN: ${e} module not found yet (will retry)`),!1;const o=n.type;function l(){return null}n.type=l;try{Object.defineProperties(n.type,Object.getOwnPropertyDescriptors(o))}catch{}return n.type.displayName=e,t.push(function(){n.type=o}),console.log(G,`PATCH: ${e} replaced (module mutation)`),!0}const Me="[ServerDrawer]";function nn(){return r.createElement(i.View,{ref:xe,style:{width:1,height:1}})}function rn(e){return e?.name==="GuildsBar"||e?.displayName==="GuildsBar"||e?.type?.name==="GuildsBar"||e?.type?.displayName==="GuildsBar"}function on(e){return ce(rn,function(t){J(t,nn),console.log(Me,"PATCH: found a real GuildsBar reference, now rendering nothing")},{persistent:!0}),e.push(function(){}),console.log(Me,"PATCH: watching for the real GuildsBar to appear"),!0}function ln(e){const t=b("ExpandedGuildFolderStore");if(!t?.getExpandedFolders)return!1;const n=function({folderId:o}){if(!c.storage.autoCollapseFolders||o==null)return;const l=t.getExpandedFolders();if(!(!(l instanceof Set)||!l.has(o)))for(const s of l)s!==o&&d.FluxDispatcher.dispatch({type:"TOGGLE_GUILD_FOLDER_EXPAND",folderId:s})};return d.FluxDispatcher.subscribe("TOGGLE_GUILD_FOLDER_EXPAND",n),e.push(function(){return d.FluxDispatcher.unsubscribe("TOGGLE_GUILD_FOLDER_EXPAND",n)}),!0}const{ScrollView:sn,View:an}=d.ReactNative;function un({children:e}){return d.React.createElement(sn,{style:{flex:1}},e,d.React.createElement(an,{style:{height:24}}))}const{View:cn,Text:dn}=d.ReactNative;function je({children:e,style:t}){return d.React.createElement(cn,{style:[{marginHorizontal:16,marginVertical:8,padding:10,borderRadius:8,borderWidth:1,borderColor:"rgba(128,128,128,0.25)"},t]},d.React.createElement(dn,{style:{fontSize:12.5,lineHeight:18,opacity:.75}},e))}const{FormSection:ze,FormSwitchRow:v}=Xe.Forms;function fn(){return L.useProxy(c.storage),d.React.createElement(un,null,d.React.createElement(je,null,"Server Drawer takes over the Quest Dock (the strip above the tab bar) to show your servers as a grid instead - tap to expand, long-press a server for its usual context menu, the chat bubble jumps to DMs, the + button creates or joins a server through Discord's own modal, and the check button marks every channel in every server as read."),d.React.createElement(ze,{title:"Layout"},d.React.createElement(v,{label:"Hide the left server rail",subLabel:"Your servers and DMs already live in the drawer, so the rail is redundant",value:c.storage.hideGuildsBar!==!1,onValueChange:function(e){c.storage.hideGuildsBar=e,Qe()}}),d.React.createElement(v,{label:"Unread badges",subLabel:"Show mention counts and unread dots on server icons in the drawer",value:c.storage.showUnreadBadges!==!1,onValueChange:function(e){c.storage.showUnreadBadges=e}}),d.React.createElement(v,{label:"Show server names",subLabel:"Word-wrapped name below each server's icon",value:c.storage.showGuildNames!==!1,onValueChange:function(e){c.storage.showGuildNames=e}}),d.React.createElement(v,{label:"Hide the DMs tile",subLabel:"Remove the DMs tile from the drawer entirely",value:!!c.storage.hideDmTile,onValueChange:function(e){c.storage.hideDmTile=e}})),d.React.createElement(ze,{title:"Folders"},d.React.createElement(v,{label:"Auto-collapse other folders",subLabel:"Opening a folder collapses any other folder that was already open",value:!!c.storage.autoCollapseFolders,onValueChange:function(e){c.storage.autoCollapseFolders=e}}),d.React.createElement(v,{label:"Hide icons in collapsed folders",subLabel:"Show a plain folder icon instead of a 4-server preview",value:!!c.storage.hideFolderIcons,onValueChange:function(e){c.storage.hideFolderIcons=e}})),d.React.createElement(je,null,"The folder options above are ported from fres621's BetterFolders - its other half (hiding icons in the native left server rail) patched a component that no longer exists in current Discord builds, so it's been rebuilt here instead, where it actually applies to what you see."))}let C=[],E;function hn(e,t){try{return t()}catch(n){return le.logger.error(`[ServerDrawer] "${e}" patch threw, skipping: ${n}`),!1}}function We(){const e={questDockContext:function(){return et(C)},expanded:function(){return tn(C)},collapsed:function(){return z("QuestDockContentCollapsed",C)},enrolledHeader:function(){return z("QuestDockEnrolledHeader",C)},unenrolledHeader:function(){return z("QuestDockUnenrolledHeader",C)},enrolledBody:function(){return z("QuestDockEnrolledBody",C)},unenrolledBody:function(){return z("QuestDockUnenrolledBody",C)},autoCollapseFolders:function(){return ln(C)},...c.storage.hideGuildsBar?{hideGuildsBar:function(){return on(C)}}:{}};$e(C);const t=new Set(Object.keys(e)),n=new Set,o=function(){for(const l of t)hn(l,e[l])&&(n.add(l),t.delete(l));t.size===0&&E&&(clearInterval(E),E=void 0)};if(o(),t.size>0){let l=0;E=setInterval(function(){o(),++l>=50&&E&&(clearInterval(E),E=void 0,t.size>0&&le.logger.error(`[ServerDrawer] Gave up waiting on: ${[...t].join(", ")}`))},200)}le.logger.log(`[ServerDrawer] onLoad: applied immediately - ${[...n].join(", ")||"none"}${t.size?`, still waiting on ${[...t].join(", ")}`:""}`)}function Ue(){E&&(clearInterval(E),E=void 0);for(const e of C)try{e()}catch{}C=[]}function Qe(){Ue(),We()}var gn={onLoad:function(){c.storage.hideGuildsBar??=!0,c.storage.showUnreadBadges??=!0,c.storage.autoCollapseFolders??=!1,c.storage.hideFolderIcons??=!1,We()},onUnload:function(){return Ue()},settings:fn};return U.default=gn,U.restart=Qe,Object.defineProperty(U,"__esModule",{value:!0}),U})({},vendetta,vendetta.plugin,vendetta.metro.common,window.React,vendetta.metro.common.ReactNative,vendetta.storage,vendetta.ui.toasts,vendetta.ui,vendetta.ui.assets,vendetta.ui.components); diff --git a/server-drawer/install/manifest.json b/server-drawer/install/manifest.json index ee1c064..a2f04d9 100644 --- a/server-drawer/install/manifest.json +++ b/server-drawer/install/manifest.json @@ -1 +1 @@ -{"name":"ServerDrawer","description":"Replaces the Quest Dock with a server grid drawer above the YouBar - tap to expand, long-press a server for its context menu, plus a one-tap create/join button.","authors":[{"name":"everestmcarthur"},{"name":"kmmiio99o"},{"name":"fres"}],"main":"index.js","vendetta":{"icon":"ServerIcon"},"hash":"ba06cf9d285b50fc243a3c26b1842f8e692311c55a1a02d8a6a7fd2ec557280b"} \ No newline at end of file +{"name":"ServerDrawer","description":"Replaces the Quest Dock with a server grid drawer above the YouBar - tap to expand, long-press a server for its context menu, plus a one-tap create/join button.","authors":[{"name":"everestmcarthur"},{"name":"kmmiio99o"},{"name":"fres"}],"main":"index.js","vendetta":{"icon":"ServerIcon"},"hash":"f1c7360f6fcbbf210173961bdb5199fd3c6f8fb57755aebeb08bee5fc9265bc2"} \ No newline at end of file