feat(plugin): User Voice Show (#694)
Co-authored-by: V <vendicated@riseup.net> Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									df7357b357
								
							
						
					
					
						commit
						e261c93563
					
				
					 4 changed files with 188 additions and 0 deletions
				
			
		
							
								
								
									
										18
									
								
								src/plugins/userVoiceShow/components/VoiceChannelSection.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/plugins/userVoiceShow/components/VoiceChannelSection.css
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | .vc-uvs-button > div { | ||||||
|  |     white-space: normal !important; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .vc-uvs-button { | ||||||
|  |     width: 100%; | ||||||
|  |     margin: auto; | ||||||
|  |     height: unset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .vc-uvs-header { | ||||||
|  |     color: var(--header-primary); | ||||||
|  |     margin-bottom: 6px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .vc-uvs-modal-margin > [class^="section"] { | ||||||
|  |     margin: 0 12px; | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								src/plugins/userVoiceShow/components/VoiceChannelSection.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/plugins/userVoiceShow/components/VoiceChannelSection.tsx
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | ||||||
|  | /* | ||||||
|  |  * Vencord, a modification for Discord's desktop app | ||||||
|  |  * Copyright (c) 2023 Vendicated and contributors | ||||||
|  |  * | ||||||
|  |  * This program is free software: you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | import "./VoiceChannelSection.css"; | ||||||
|  | 
 | ||||||
|  | import { findByCodeLazy, findByPropsLazy } from "@webpack"; | ||||||
|  | import { Button, Forms, PermissionStore, Toasts } from "@webpack/common"; | ||||||
|  | import { Channel } from "discord-types/general"; | ||||||
|  | 
 | ||||||
|  | const ChannelActions = findByPropsLazy("selectChannel", "selectVoiceChannel"); | ||||||
|  | const UserPopoutSection = findByCodeLazy(".lastSection", ".children"); | ||||||
|  | 
 | ||||||
|  | const CONNECT = 1n << 20n; | ||||||
|  | 
 | ||||||
|  | interface VoiceChannelFieldProps { | ||||||
|  |     channel: Channel; | ||||||
|  |     label: string; | ||||||
|  |     showHeader: boolean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const VoiceChannelSection = ({ channel, label, showHeader }: VoiceChannelFieldProps) => ( | ||||||
|  |     <UserPopoutSection> | ||||||
|  |         {showHeader && <Forms.FormTitle className="vc-uvs-header">In a voice channel</Forms.FormTitle>} | ||||||
|  |         <Button | ||||||
|  |             className="vc-uvs-button" | ||||||
|  |             color={Button.Colors.TRANSPARENT} | ||||||
|  |             size={Button.Sizes.SMALL} | ||||||
|  | 
 | ||||||
|  |             onClick={() => { | ||||||
|  |                 if (PermissionStore.can(CONNECT, channel)) | ||||||
|  |                     ChannelActions.selectVoiceChannel(channel.id); | ||||||
|  |                 else | ||||||
|  |                     Toasts.show({ | ||||||
|  |                         message: "Insufficient permissions to enter the channel.", | ||||||
|  |                         id: "user-voice-show-insufficient-permissions", | ||||||
|  |                         type: Toasts.Type.FAILURE, | ||||||
|  |                         options: { | ||||||
|  |                             position: Toasts.Position.BOTTOM, | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |             }} | ||||||
|  |         > | ||||||
|  |             {label} | ||||||
|  |         </Button> | ||||||
|  |     </UserPopoutSection> | ||||||
|  | ); | ||||||
							
								
								
									
										105
									
								
								src/plugins/userVoiceShow/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/plugins/userVoiceShow/index.tsx
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,105 @@ | ||||||
|  | /* | ||||||
|  |  * Vencord, a modification for Discord's desktop app | ||||||
|  |  * Copyright (c) 2023 Vendicated and contributors | ||||||
|  |  * | ||||||
|  |  * This program is free software: you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | import { definePluginSettings } from "@api/settings"; | ||||||
|  | import ErrorBoundary from "@components/ErrorBoundary"; | ||||||
|  | import { Devs } from "@utils/constants"; | ||||||
|  | import definePlugin, { OptionType } from "@utils/types"; | ||||||
|  | import { findStoreLazy } from "@webpack"; | ||||||
|  | import { ChannelStore, GuildStore } from "@webpack/common"; | ||||||
|  | import { User } from "discord-types/general"; | ||||||
|  | 
 | ||||||
|  | import { VoiceChannelSection } from "./components/VoiceChannelSection"; | ||||||
|  | 
 | ||||||
|  | const VoiceStateStore = findStoreLazy("VoiceStateStore"); | ||||||
|  | 
 | ||||||
|  | const settings = definePluginSettings({ | ||||||
|  |     showInUserProfileModal: { | ||||||
|  |         type: OptionType.BOOLEAN, | ||||||
|  |         description: "Show a user's voice channel in their profile modal", | ||||||
|  |         default: true, | ||||||
|  |     }, | ||||||
|  |     showVoiceChannelSectionHeader: { | ||||||
|  |         type: OptionType.BOOLEAN, | ||||||
|  |         description: 'Whether to show "IN A VOICE CHANNEL" above the join button', | ||||||
|  |         default: true, | ||||||
|  |     } | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | interface UserProps { | ||||||
|  |     user: User; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const VoiceChannelField = ErrorBoundary.wrap(({ user }: UserProps) => { | ||||||
|  |     const { channelId } = VoiceStateStore.getVoiceStateForUser(user.id) ?? {}; | ||||||
|  |     if (!channelId) return null; | ||||||
|  | 
 | ||||||
|  |     const channel = ChannelStore.getChannel(channelId); | ||||||
|  |     const guild = GuildStore.getGuild(channel.guild_id); | ||||||
|  | 
 | ||||||
|  |     if (!guild) return null; // When in DM call
 | ||||||
|  | 
 | ||||||
|  |     const result = `${guild.name} | ${channel.name}`; | ||||||
|  | 
 | ||||||
|  |     return ( | ||||||
|  |         <VoiceChannelSection | ||||||
|  |             channel={channel} | ||||||
|  |             label={result} | ||||||
|  |             showHeader={settings.store.showVoiceChannelSectionHeader} | ||||||
|  |         /> | ||||||
|  |     ); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | export default definePlugin({ | ||||||
|  |     name: "UserVoiceShow", | ||||||
|  |     description: "Shows whether a User is currently in a voice channel somewhere in their profile", | ||||||
|  |     authors: [Devs.LordElias], | ||||||
|  |     settings, | ||||||
|  | 
 | ||||||
|  |     patchModal({ user }: UserProps) { | ||||||
|  |         if (!settings.store.showInUserProfileModal) | ||||||
|  |             return null; | ||||||
|  | 
 | ||||||
|  |         return ( | ||||||
|  |             <div className="vc-uvs-modal-margin"> | ||||||
|  |                 <VoiceChannelField user={user} /> | ||||||
|  |             </div> | ||||||
|  |         ); | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     patchPopout: ({ user }: UserProps) => <VoiceChannelField user={user} />, | ||||||
|  | 
 | ||||||
|  |     patches: [ | ||||||
|  |         { | ||||||
|  |             find: ".showCopiableUsername", | ||||||
|  |             replacement: { | ||||||
|  |                 match: /\(0,\w\.jsx\)\(\w{2},{user:\w,setNote/, | ||||||
|  |                 // paste my fancy custom button above the message field
 | ||||||
|  |                 replace: "$self.patchPopout(arguments[0]),$&", | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             find: ".USER_PROFILE_MODAL", | ||||||
|  |             replacement: { | ||||||
|  |                 match: /,{user:\w{1,2}}\)(?!;case)/, | ||||||
|  |                 // paste my fancy custom button below the username
 | ||||||
|  |                 replace: "$&,$self.patchModal(arguments[0])", | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     ], | ||||||
|  | }); | ||||||
|  | @ -226,6 +226,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ | ||||||
|         name: "TheKodeToad", |         name: "TheKodeToad", | ||||||
|         id: 706152404072267788n |         id: 706152404072267788n | ||||||
|     }, |     }, | ||||||
|  |     LordElias: { | ||||||
|  |         name: "LordElias", | ||||||
|  |         id: 319460781567639554n | ||||||
|  |     }, | ||||||
|     juby: { |     juby: { | ||||||
|         name: "Juby210", |         name: "Juby210", | ||||||
|         id: 324622488644616195n |         id: 324622488644616195n | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue