PreviewMessage: Add attachments (& misc changes) (#1715)
This commit is contained in:
		
							parent
							
								
									cf7c4d63b6
								
							
						
					
					
						commit
						a73d09a2f0
					
				
					 11 changed files with 108 additions and 8 deletions
				
			
		
							
								
								
									
										6
									
								
								src/plugins/favEmojiFirst/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/plugins/favEmojiFirst/README.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | # FavoriteEmojiFirst | ||||||
|  | 
 | ||||||
|  | Puts your favorite emoji first in the emoji autocomplete. | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								src/plugins/favGifSearch/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/plugins/favGifSearch/README.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | # FavoriteGifSearch | ||||||
|  | 
 | ||||||
|  | Adds a search bar to favorite gifs. | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -87,7 +87,7 @@ export const settings = definePluginSettings({ | ||||||
| export default definePlugin({ | export default definePlugin({ | ||||||
|     name: "FavoriteGifSearch", |     name: "FavoriteGifSearch", | ||||||
|     authors: [Devs.Aria], |     authors: [Devs.Aria], | ||||||
|     description: "Adds a search bar for favorite gifs", |     description: "Adds a search bar to favorite gifs.", | ||||||
| 
 | 
 | ||||||
|     patches: [ |     patches: [ | ||||||
|         { |         { | ||||||
							
								
								
									
										6
									
								
								src/plugins/imageZoom/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/plugins/imageZoom/README.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | # ImageZoom | ||||||
|  | 
 | ||||||
|  | Lets you zoom in to images and gifs. Use scroll wheel to zoom in and shift + scroll wheel to increase lens radius / size | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -99,6 +99,15 @@ const imageContextMenuPatch: NavContextMenuPatchCallback = children => () => { | ||||||
|                     ContextMenu.close(); |                     ContextMenu.close(); | ||||||
|                 }} |                 }} | ||||||
|             /> |             /> | ||||||
|  |             <Menu.MenuCheckboxItem | ||||||
|  |                 id="vc-nearest-neighbour" | ||||||
|  |                 label="Nearset Neighbour" | ||||||
|  |                 checked={settings.store.nearestNeighbour} | ||||||
|  |                 action={() => { | ||||||
|  |                     settings.store.nearestNeighbour = !settings.store.nearestNeighbour; | ||||||
|  |                     ContextMenu.close(); | ||||||
|  |                 }} | ||||||
|  |             /> | ||||||
|             <Menu.MenuControlItem |             <Menu.MenuControlItem | ||||||
|                 id="vc-zoom" |                 id="vc-zoom" | ||||||
|                 label="Zoom" |                 label="Zoom" | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								src/plugins/previewMessage/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/plugins/previewMessage/README.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | # PreviewMessage | ||||||
|  | 
 | ||||||
|  | Lets you preview your message before sending it. | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -16,37 +16,96 @@ | ||||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| import { sendBotMessage } from "@api/Commands"; | import { generateId, sendBotMessage } from "@api/Commands"; | ||||||
| import ErrorBoundary from "@components/ErrorBoundary"; | import ErrorBoundary from "@components/ErrorBoundary"; | ||||||
| import { Devs } from "@utils/constants"; | import { Devs } from "@utils/constants"; | ||||||
| import definePlugin from "@utils/types"; | import definePlugin from "@utils/types"; | ||||||
|  | import { findByPropsLazy } from "@webpack"; | ||||||
| import { Button, ButtonLooks, ButtonWrapperClasses, DraftStore, DraftType, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; | import { Button, ButtonLooks, ButtonWrapperClasses, DraftStore, DraftType, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; | ||||||
|  | import { MessageAttachment } from "discord-types/general"; | ||||||
| 
 | 
 | ||||||
| interface Props { | interface Props { | ||||||
|     type: { |     type: { | ||||||
|         analyticsName: string; |         analyticsName: string; | ||||||
|  |         isEmpty: boolean; | ||||||
|  |         attachments: boolean; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const UploadStore = findByPropsLazy("getUploads"); | ||||||
|  | 
 | ||||||
| const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage); | const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | const getImageBox = (url: string): Promise<{ width: number, height: number; } | null> => | ||||||
|  |     new Promise(res => { | ||||||
|  |         const img = new Image(); | ||||||
|  |         img.onload = () => | ||||||
|  |             res({ width: img.width, height: img.height }); | ||||||
|  | 
 | ||||||
|  |         img.onerror = () => | ||||||
|  |             res(null); | ||||||
|  | 
 | ||||||
|  |         img.src = url; | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | const getAttachments = async (channelId: string) => | ||||||
|  |     await Promise.all( | ||||||
|  |         UploadStore.getUploads(channelId, DraftType.ChannelMessage) | ||||||
|  |             .map(async (upload: any) => { | ||||||
|  |                 const { isImage, filename, spoiler, item: { file } } = upload; | ||||||
|  |                 const url = URL.createObjectURL(file); | ||||||
|  |                 const attachment: MessageAttachment = { | ||||||
|  |                     id: generateId(), | ||||||
|  |                     filename: spoiler ? "SPOILER_" + filename : filename, | ||||||
|  |                     // weird eh? if i give it the normal content type the preview doenst work
 | ||||||
|  |                     content_type: undefined, | ||||||
|  |                     size: await upload.getSize(), | ||||||
|  |                     spoiler, | ||||||
|  |                     // discord adds query params to the url, so we need to add a hash to prevent that
 | ||||||
|  |                     url: url + "#", | ||||||
|  |                     proxy_url: url + "#", | ||||||
|  |                 }; | ||||||
|  | 
 | ||||||
|  |                 if (isImage) { | ||||||
|  |                     const box = await getImageBox(url); | ||||||
|  |                     if (!box) return attachment; | ||||||
|  | 
 | ||||||
|  |                     attachment.width = box.width; | ||||||
|  |                     attachment.height = box.height; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 return attachment; | ||||||
|  |             }) | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| export function PreviewButton(chatBoxProps: Props) { | export function PreviewButton(chatBoxProps: Props) { | ||||||
|  |     const { isEmpty, attachments } = chatBoxProps.type; | ||||||
|  | 
 | ||||||
|     const channelId = SelectedChannelStore.getChannelId(); |     const channelId = SelectedChannelStore.getChannelId(); | ||||||
|     const draft = useStateFromStores([DraftStore], () => getDraft(channelId)); |     const draft = useStateFromStores([DraftStore], () => getDraft(channelId)); | ||||||
|  | 
 | ||||||
|     if (chatBoxProps.type.analyticsName !== "normal") return null; |     if (chatBoxProps.type.analyticsName !== "normal") return null; | ||||||
|     if (!draft) return null; | 
 | ||||||
|  |     const hasAttachments = attachments && UploadStore.getUploads(channelId, DraftType.ChannelMessage).length > 0; | ||||||
|  |     const hasContent = !isEmpty && draft?.length > 0; | ||||||
|  | 
 | ||||||
|  |     if (!hasContent && !hasAttachments) return null; | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|         <Tooltip text="Preview Message"> |         <Tooltip text="Preview Message"> | ||||||
|             {tooltipProps => ( |             {tooltipProps => ( | ||||||
|                 <Button |                 <Button | ||||||
|                     {...tooltipProps} |                     {...tooltipProps} | ||||||
|                     onClick={() => |                     onClick={async () => | ||||||
|                         sendBotMessage( |                         sendBotMessage( | ||||||
|                             channelId, |                             channelId, | ||||||
|                             { |                             { | ||||||
|                                 content: getDraft(channelId), |                                 content: getDraft(channelId), | ||||||
|                                 author: UserStore.getCurrentUser() |                                 author: UserStore.getCurrentUser(), | ||||||
|  |                                 attachments: hasAttachments ? await getAttachments(channelId) : undefined, | ||||||
|                             } |                             } | ||||||
|                         )} |                         )} | ||||||
|                     size="" |                     size="" | ||||||
|  | @ -66,7 +125,7 @@ export function PreviewButton(chatBoxProps: Props) { | ||||||
| 
 | 
 | ||||||
| export default definePlugin({ | export default definePlugin({ | ||||||
|     name: "PreviewMessage", |     name: "PreviewMessage", | ||||||
|     description: "Lets you preview your message before sending it", |     description: "Lets you preview your message before sending it.", | ||||||
|     authors: [Devs.Aria], |     authors: [Devs.Aria], | ||||||
|     patches: [ |     patches: [ | ||||||
|         { |         { | ||||||
							
								
								
									
										5
									
								
								src/plugins/searchReply/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/plugins/searchReply/README.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | # SearchReply | ||||||
|  | 
 | ||||||
|  | Adds a reply button to search results. | ||||||
|  | 
 | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								src/webpack/common/types/menu.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								src/webpack/common/types/menu.d.ts
									
									
									
									
										vendored
									
									
								
							|  | @ -65,8 +65,13 @@ export interface Menu { | ||||||
|         id: string; |         id: string; | ||||||
|         interactive?: boolean; |         interactive?: boolean; | ||||||
|     }>; |     }>; | ||||||
|     // TODO: Type me
 |     MenuSliderControl: RC<{ | ||||||
|     MenuSliderControl: RC<any>; |         minValue: number, | ||||||
|  |         maxValue: number, | ||||||
|  |         value: number, | ||||||
|  |         onChange(value: number): void, | ||||||
|  |         renderValue?(value: number): string, | ||||||
|  |     }>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface ContextMenuApi { | export interface ContextMenuApi { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue