4 lines
15 KiB
JavaScript
4 lines
15 KiB
JavaScript
(function(v,g,o,a,c,H,h,S,b,R){"use strict";function T(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function N(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function I(e,t,n){return t&&N(e.prototype,t),n&&N(e,n),e}const y=H.storage;var u=function(e){return e.Useful="Useful",e.Fixes="Fixes",e.Fun="Fun",e}({});(function(){function e(){T(this,e)}return I(e,[{key:"add",value:function(t){this.store.push(t)}},{key:"unpatch",value:function(){for(const t of this.store)try{t()}catch{}this.store=[]}}]),e})();let d=function(){function e({id:t,label:n,meta:r,settings:i,handlers:s}){T(this,e),this.id=t,this.label=n,this.meta=r,this.settings=i??{},this.handlers=s}return I(e,[{key:"storage",get:function(){const t=Object.fromEntries(Object.entries(this.settings).filter(function([,n]){return"default"in n}).map(function([n,r]){return[n,r.default]}));y.modules[this.id]??={enabled:!1,options:t};for(const[n,r]of Object.entries(t)){const i=y.modules[this.id].options;typeof r!=typeof i[n]&&(i[n]=r)}return y.modules[this.id]}},{key:"toggle",value:function(){this.storage.enabled=!this.storage.enabled,this.storage.enabled?this.start():this.stop(),this.refresh()}},{key:"restart",value:function(){this.started&&(this.stop(),this.start(),this.refresh())}},{key:"start",value:function(){if(!this.started){try{this.started=!0,this.handlers.onStart.call(this)}catch(t){this.stop(),this.started=!1;const n=t instanceof Error?t:new Error(String(t));g.logger.error(`[RoseUtils/${this.label}] Failed to start: ${n}`),this.errors.Start=String(n.stack??n),h.showToast(`${this.label} failed to start - see RoseUtils settings for details`,void 0)}this.refresh()}}},{key:"stop",value:function(){if(this.started){try{this.started=!1,this.handlers.onStop.call(this)}catch(t){const n=t instanceof Error?t:new Error(String(t));g.logger.error(`[RoseUtils/${this.label}] Failed to stop cleanly: ${n}`),this.errors.Stop=String(n.stack??n)}finally{this.patches.unpatch()}this.refresh()}}},{key:"refresh",value:function(){this.listeners.forEach(function(t){return t()})}},{key:"useRefresh",value:function(){var t=this;const[,n]=a.React.useReducer(function(r){return~r},0);a.React.useEffect(function(){return t.listeners.add(n),function(){t.listeners.delete(n)}},[])}}]),e}();var K="d170a10bd3781e4a.png";function w(e,t,n=!1){const r=function(...i){n&&a.FluxDispatcher.unsubscribe(e,r),t(...i)};return a.FluxDispatcher.subscribe(e,r),function(){return a.FluxDispatcher.unsubscribe(e,r)}}const J=o.findByStoreName("SpotifyProtocolStore"),p=o.findByStoreName("SpotifyStore"),q=o.findByStoreName("UserStore"),{play:L,sync:E}=o.findByProps("play","sync")??{};function Q(e,t,n){if(typeof e=="string")return h.showToast(e,void 0);if(!L||!E)return h.showToast("Couldn't find Spotify's sync action - this feature may be unavailable on your Discord version.",void 0);if(p?.getActivity())return E(t,n);w("SPOTIFY_PLAYER_STATE",function(){return E(t,n)},!0),L(t,n)}function X(e){const[t,n]=a.React.useReducer(function(l){return~l},0);a.React.useEffect(function(){return w("SPOTIFY_PLAYER_STATE",n)});const r=e.party.id.split(":")[1],i=a.React.useMemo(function(){const l=q?.getCurrentUser?.()?.id,A=p?.getActivity?.(),C=!!p?.hasConnectedAccount?.(),f=!!p?.getActiveSocketAndDevice?.()||!!J?.isProtocolRegistered?.();return{isYou:l===r,isListeningAlong:A?.party?.id===e.party.id,isPlayable:C&&f}},[r,e,t]);let s=!1;return i.isYou?s="Listen along with someone else, not yourself.":i.isListeningAlong?s="You're already along for this ride.":i.isPlayable||(s="Spotify is not detected"),{disabled:s,userId:r}}function Z(){const[e,t]=a.React.useState(!1);return{loading:e,trigger:function(){return t(!0),setTimeout(function(){return t(!1)},5e3)}}}function ee({button:e,activity:t}){const{disabled:n,userId:r}=X(t),{loading:i,trigger:s}=Z(),l=i&&!n;return React.createElement(a.ReactNative.View,{style:{flexDirection:"row",flex:1}},React.createElement(a.ReactNative.View,{style:{paddingRight:6}},React.createElement(S.Button,{size:"small",text:"",style:[e?.style,{width:32},!!n&&{opacity:.5}],renderIcon:function(){return l?React.createElement(a.ReactNative.ActivityIndicator,{size:"small",color:"#fff"}):React.createElement(a.ReactNative.Image,{source:K,style:{width:20,height:20,tintColor:"#fff"}})},onPress:function(){return!l&&(Q(n,t,r),!n&&s())}})),React.createElement(a.ReactNative.View,{style:{flexGrow:1}},React.createElement(S.Button,e)))}const B=o.findByProps("SpotifyPlayButton");var te=new d({id:"spotify-listen-along",label:"Add Listen Along",meta:{sublabel:"Ports the Spotify listen along feature from desktop to mobile in Spotify activities",category:u.Useful},handlers:{onStart(){B?.SpotifyPlayButton&&this.patches.add(c.after("SpotifyPlayButton",B,function([e],t){if(t)return a.React.createElement(ee,{button:t.props,activity:e?.activity})}))},onStop(){}}});const x=o.findByProps("downloadMediaAsset"),P=o.findByProps("useMediaShareActions");function D(e){const t=e.split("/"),n=t.findIndex(function(l){return l.endsWith(".tenor.com")});if(n===-1)return;const[r,i,s]=t.slice(n,n+3);if(!(!r||!i||!s))return`https://${r}/${i.slice(0,-2)}AC/${s.split(".")[0]}.gif`}var ne=new d({id:"tenor-gif-fix",label:"Tenor GIF Fix",meta:{sublabel:"Fixes a several-year old bug which downloads gifs from Tenor as videos instead of gif files",category:u.Fixes},handlers:{onStart(){x?.downloadMediaAsset&&this.patches.add(c.before("downloadMediaAsset",x,function(e){const t=e[0];if(!t||typeof t!="string")return;const n=D(t);n&&(e[0]=n,e[1]=1)})),P?.useMediaShareActions&&this.patches.add(c.before("useMediaShareActions",P,function(e){const t=e[0]?.source;if(!t?.uri)return;const n=D(t.uri);n&&(t.sourceURI=n,delete t.videoURI)}))},onStop(){}}});const{View:ae,TouchableOpacity:re,Image:ie}=a.ReactNative,U=o.findByStoreName("SpotifyStore"),se=o.findByStoreName("SelectedChannelStore"),oe=o.findByStoreName("DraftStore"),k=o.findByProps("sendMessage","revealMessage"),m=o.findByProps("clearDraft"),le=function(){if(!k?.sendMessage||!m?.clearDraft)return;const e=U?.getActivity?.();if(!e?.party?.id)return;const t=se?.getChannelId?.();t&&(k.sendMessage(t,{content:oe?.getDraft?.(t,0)??"",tts:!1,invalidEmojis:[],validNonShortcutEmojis:[]},!0,{activityAction:{activity:e,type:3}}),m.clearDraft(t,0))};function ce(){const[,e]=a.React.useReducer(function(r){return~r},0);a.React.useEffect(function(){return w("SPOTIFY_PLAYER_STATE",e)});const t=!!(k?.sendMessage&&m?.clearDraft&&U?.getActivity?.()?.party?.id),n=b.getAssetByID(b.getAssetIDByName("ic_spotify_white_16px"));return a.React.createElement(ae,{style:{opacity:t?1:.4,paddingHorizontal:8,justifyContent:"center"}},a.React.createElement(re,{disabled:!t,onPress:le},n?.uri?a.React.createElement(ie,{source:{uri:n.uri},style:{width:22,height:22}}):a.React.createElement(a.ReactNative.Text,{style:{color:"#1ED760",fontWeight:"700"}},"\u266B")))}const M=o.findByTypeName("MediaKeyboardListHeader",!1);var ue=new d({id:"send-spotify-invite",label:"Send Spotify invite",meta:{sublabel:"Adds a button in the chat attachment menu to invite the channel to listen along to Spotify",category:u.Useful},handlers:{onStart(){M&&this.patches.add(c.after("type",M,function(e,t){if(!(!t?.props||!Array.isArray(t.props.children)))return{...t,props:{...t.props,children:[...t.props.children,a.React.createElement(ce,{})]}}}))},onStop(){}}});function de(e){const{NativeModules:t}=a.ReactNative,n=t?.DCDChatManager;if(n?.updateRows)return c.before("updateRows",n,function(i){try{const s=JSON.parse(i[1]);e(s),i[1]=JSON.stringify(s)}catch{}});const r=o.findByName("RowManager",!1);return r?.prototype?.generate?c.after("generate",r.prototype,function(i,s){try{e([s])}catch{}}):function(){}}const _=o.findByStoreName("GuildMemberStore");var fe=new d({id:"minimod",label:"Minimod",meta:{sublabel:"Lets you see some moderator-only things, like whether a member is currently timed out",category:u.Fun},settings:{showTimeouts:{label:"Show timeouts",subLabel:"Show member timeout icons in chat",type:"toggle",default:!0}},handlers:{onStart(){!this.storage.options.showTimeouts||!_?.getCommunicationDisabledUserMap||this.patches.add(de(function(e){if(!e.some(function(r){return"message"in r}))return;const t=_.getCommunicationDisabledUserMap(),n=Date.now();for(const r of e)r.type===1&&new Date(t[`${r.message.guildId}-${r.message.authorId}`]).getTime()>n&&(r.message.communicationDisabled=!0)}))},onStop(){}}});const ge=o.findByStoreName("ThemeStore"),he=o.find(function(e){return e?.default?.internal?.resolveSemanticColor})?.default?.internal?.resolveSemanticColor??o.find(function(e){return e?.meta?.resolveSemanticColor})?.meta?.resolveSemanticColor??function(){};function V(e,t=ge?.theme){if(e)try{return he(t,e)}catch{return}}const{View:be,Text:ye}=a.ReactNative,W={destructive:{bg:"#F23F42",fg:"#FFFFFF"},default:{bg:"#4E5058",fg:"#FFFFFF"}};function pe({variant:e="default",children:t}){const n=W[e]??W.default;return a.React.createElement(be,{style:{backgroundColor:n.bg,borderRadius:4,paddingHorizontal:4,paddingVertical:1,marginLeft:4,alignSelf:"center"}},a.React.createElement(ye,{style:{color:n.fg,fontSize:10,fontWeight:"700",textTransform:"uppercase"}},t))}var ve="f47fd463dcaac61e.png",Se="f944dbd033a60207.png",Re="88eacd3588829ded.png",we="4d1aef97fe869aaf.png",Ee="3a73d84a21043a5e.png",ke="8b628d7e3fc05957.png",me="cb7a2c9b3fb9561c.png",Fe="11d89273b5bd6cc6.png",$e="ea31146eb15fdde7.png",Ae="b0d124bd12658047.png",Ce="cb8b45023e70bb61.png",Te="a738efc867a225ee.png",Ne="cba17334eeaf3198.png",Ie="fead9e69933db668.png",Le="fead9e69933db668.png",Be="d6a4e512cdcf1078.png",xe="9901722947705011.png",Pe=function(e){return e.Lock="Lock",e.Warning="Warning",e.Controller="Controller",e}(Pe||{});function De(e,t){if(e==="Lock")return t?$e:Fe;if(e==="Warning")return t?xe:Be;if(e==="Controller")return Re}const Ue={Lock:["#f0b232","STATUS_WARNING"],Warning:["#f23f43","STATUS_DANGER"],Controller:["#23a55a","STATUS_POSITIVE"]},Me=[{name:"Announcements",kind:"Lock",base:ve},{name:"Announcements",kind:"Warning",base:Se},{name:"Text",kind:"Lock",base:Te},{name:"Text",kind:"Warning",base:Ne},{name:"Text",kind:"Controller",base:Ce},{name:"Voice",kind:"Lock",base:Ie},{name:"Voice",kind:"Warning",base:Le},{name:"Forum",kind:"Lock",base:we},{name:"Forum",kind:"Warning",base:Ee},{name:"Stage",kind:"Lock",bottom:!0,base:Ae},{name:"Stage",kind:"Warning",bottom:!0,base:0},{name:"Image",kind:"Lock",bottom:!0,base:ke},{name:"Image",kind:"Warning",bottom:!0,base:me}],O=o.findByName("ChannelInfo",!1),j=o.findByProps("BaseChannelIcon");var _e=new d({id:"colorful-channels",label:"Colorful Channels",meta:{sublabel:"Gives channel icons with symbols colors to make them more aesthetically pleasing",category:u.Useful},settings:{nsfwTag:{label:"NSFW tag",subLabel:"Adds a red NSFW tag next to channel names",type:"toggle",default:!0},colorIcons:{label:"Colored icon symbols",subLabel:"Turns locked channel symbols yellow, NSFW channel symbols red",type:"toggle",default:!0},colorIconsFallback:{label:"Fallback colors for colored icon symbols",subLabel:"Uses yellow, red and green colors regardless of theme",type:"toggle",default:!1}},handlers:{onStart(){var e=this;this.storage.options.nsfwTag&&O&&this.patches.add(c.after("default",O,function([{channel:t}],n){return a.React.createElement(a.React.Fragment,{},t?.nsfw_&&a.React.createElement(pe,{variant:"destructive"},"nsfw"),n)})),this.storage.options.colorIcons&&j?.BaseChannelIcon&&this.patches.add(c.after("BaseChannelIcon",j,function([{source:t,style:n}],r){try{const i=typeof t?.original=="number"?b.getAssetByID(t.original)?.name:typeof t=="number"?b.getAssetByID(t)?.name:null;if(!i)return;const s=Me.find(function(G){return i===`${G.name}${G.kind}Icon`});if(!s)return;const[l,A]=Ue[s.kind],C=De(s.kind,s.bottom),f=r?.props?.color?.replace(/-/g,"_")?.toUpperCase(),Ze=f&&R.semanticColors?.[f]?V(R.semanticColors[f]):void 0,z=a.ReactNative.StyleSheet.flatten([n,r?.props?.style,{width:18,height:18,tintColor:Ze}]),et=e.storage.options.colorIconsFallback?l:V(R.semanticColors?.[A])??l;return a.React.createElement(a.ReactNative.View,{},a.React.createElement(a.ReactNative.Image,{style:z,source:s.base}),a.React.createElement(a.ReactNative.View,{style:{position:"absolute",right:0,bottom:0}},a.React.createElement(a.ReactNative.Image,{style:{...z,tintColor:et},source:C})))}catch{return}}))},onStop(){}}}),F=[te,ne,ue,fe,_e];const{ScrollView:Ve,View:We}=a.ReactNative;function Oe({children:e}){return a.React.createElement(Ve,{style:{flex:1}},e,a.React.createElement(We,{style:{height:24}}))}const{View:je,Text:Ye}=a.ReactNative;function ze({children:e,style:t}){return a.React.createElement(je,{style:[{marginHorizontal:16,marginVertical:8,padding:10,borderRadius:8,borderWidth:1,borderColor:"rgba(128,128,128,0.25)"},t]},a.React.createElement(Ye,{style:{fontSize:12.5,lineHeight:18,opacity:.75}},e))}const{FormSection:Ge,FormSwitchRow:Y,FormRow:$}=S.Forms;function He(e,t){return typeof e.subLabel=="function"?e.subLabel(t):e.subLabel}function Ke({module:e,settingKey:t}){const n=e.settings[t];if(n.predicate&&!n.predicate.call(e))return null;const r=e.storage.options[t],i=He(n,r),s=!e.storage.enabled;return n.type==="toggle"?a.React.createElement(Y,{label:n.label,subLabel:i,value:!!r,disabled:s,onValueChange:function(l){e.storage.options[t]=l,e.restart()}}):n.type==="button"?a.React.createElement($,{label:n.label,subLabel:i,disabled:s,onPress:function(){return n.action.call(e)}}):a.React.createElement($,{label:n.label,subLabel:[i,r].filter(Boolean).join(" - "),disabled:s,onPress:function(){const l=n.choices.indexOf(r);e.storage.options[t]=n.choices[(l+1)%n.choices.length],e.restart()}})}function Je({module:e}){e.useRefresh();const t=Object.entries(e.errors);return a.React.createElement(Ge,{title:e.label},a.React.createElement(Y,{label:"Enabled",subLabel:e.meta.sublabel,value:!!e.storage.enabled,onValueChange:function(){return e.toggle()}}),e.storage.enabled&&Object.keys(e.settings).map(function(n){return a.React.createElement(Ke,{key:n,module:e,settingKey:n})}),t.length>0&&a.React.createElement($,{label:`${t.length} error${t.length===1?"":"s"} - tap to copy`,onPress:function(){const n=t.map(function([r,i]){return`[${e.label}] ${r}
|
|
${i}`}).join(`
|
|
|
|
`);a.clipboard.setString(n),h.showToast("Copied - paste this when reporting the issue",void 0)}}))}const qe=[u.Useful,u.Fixes,u.Fun];function Qe(){return a.React.createElement(Oe,null,a.React.createElement(ze,null,"RoseUtils is a collection of small, independent utilities - toggle whichever ones you want. Fork of nexpid's NexxUtils, with fixes for lookups that broke on newer Discord versions. If a module shows an error below, tap it to copy the details for a bug report."),qe.flatMap(function(e){return F.filter(function(t){return t.meta.category===e}).map(function(t){return a.React.createElement(Je,{key:t.id,module:t})})}))}var Xe={onLoad(){y.modules??={};for(const e of F)try{e.storage.enabled&&e.start()}catch(t){g.logger.error(`[RoseUtils] Failed to start "${e.label}" on load: ${t}`)}},onUnload(){for(const e of F)try{e.stop()}catch(t){g.logger.error(`[RoseUtils] Failed to stop "${e.label}" cleanly: ${t}`)}},settings:Qe};return v.default=Xe,Object.defineProperty(v,"__esModule",{value:!0}),v})({},vendetta,vendetta.metro,vendetta.metro.common,vendetta.patcher,vendetta.plugin,vendetta.ui.toasts,vendetta.ui.components,vendetta.ui.assets,vendetta.ui);
|