quickReply => InteractionKeybinds: now supports edits (#95)
This commit is contained in:
		
							parent
							
								
									8817e2dff7
								
							
						
					
					
						commit
						a73e10fc77
					
				
					 2 changed files with 133 additions and 61 deletions
				
			
		
							
								
								
									
										133
									
								
								src/plugins/interactionKeybinds.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/plugins/interactionKeybinds.ts
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,133 @@ | ||||||
|  | import definePlugin from "../utils/types"; | ||||||
|  | import { Devs } from "../utils/constants"; | ||||||
|  | import { FluxDispatcher as Dispatcher, ChannelStore, SelectedChannelStore, UserStore } from "../webpack/common"; | ||||||
|  | import { filters } from "../webpack"; | ||||||
|  | import { lazyWebpack } from "../utils/misc"; | ||||||
|  | import { Message } from "discord-types/general"; | ||||||
|  | 
 | ||||||
|  | const MessageStore = lazyWebpack(filters.byProps(["getRawMessages"])); | ||||||
|  | 
 | ||||||
|  | const isMac = navigator.platform.includes("Mac"); // bruh
 | ||||||
|  | let replyIdx = -1; | ||||||
|  | let editIdx = -1; | ||||||
|  | 
 | ||||||
|  | export default definePlugin({ | ||||||
|  |     name: "InteractionKeybinds", | ||||||
|  |     authors: [Devs.obscurity, Devs.Ven], | ||||||
|  |     description: "Reply to (ctrl + up/down) and edit (ctrl + shift + up/down) messages via keybinds", | ||||||
|  | 
 | ||||||
|  |     start() { | ||||||
|  |         Dispatcher.subscribe("DELETE_PENDING_REPLY", onDeletePendingReply); | ||||||
|  |         Dispatcher.subscribe("MESSAGE_END_EDIT", onEndEdit); | ||||||
|  |         Dispatcher.subscribe("MESSAGE_START_EDIT", onStartEdit); | ||||||
|  |         Dispatcher.subscribe("CREATE_PENDING_REPLY", onCreatePendingReply); | ||||||
|  |         document.addEventListener("keydown", onKeydown); | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     stop() { | ||||||
|  |         Dispatcher.unsubscribe("DELETE_PENDING_REPLY", onDeletePendingReply); | ||||||
|  |         Dispatcher.unsubscribe("MESSAGE_END_EDIT", onEndEdit); | ||||||
|  |         Dispatcher.unsubscribe("MESSAGE_START_EDIT", onStartEdit); | ||||||
|  |         Dispatcher.unsubscribe("CREATE_PENDING_REPLY", onCreatePendingReply); | ||||||
|  |         document.removeEventListener("keydown", onKeydown); | ||||||
|  |     }, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const onDeletePendingReply = () => replyIdx = -1; | ||||||
|  | const onEndEdit = () => editIdx = -1; | ||||||
|  | 
 | ||||||
|  | function calculateIdx(messages: Message[], id: string) { | ||||||
|  |     const idx = messages.findIndex(m => m.id === id); | ||||||
|  |     return idx === -1 | ||||||
|  |         ? idx | ||||||
|  |         : messages.length - idx - 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function onStartEdit({ channelId, messageId, _isQuickEdit }: any) { | ||||||
|  |     if (_isQuickEdit) return; | ||||||
|  | 
 | ||||||
|  |     const meId = UserStore.getCurrentUser().id; | ||||||
|  | 
 | ||||||
|  |     const messages = MessageStore.getMessages(channelId)._array.filter(m => m.author.id === meId); | ||||||
|  |     editIdx = calculateIdx(messages, messageId); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function onCreatePendingReply({ message, _isQuickReply }: { message: Message; _isQuickReply: boolean; }) { | ||||||
|  |     if (_isQuickReply) return; | ||||||
|  | 
 | ||||||
|  |     replyIdx = calculateIdx(MessageStore.getMessages(message.channel_id)._array, message.id); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const isCtrl = (e: KeyboardEvent) => isMac ? e.metaKey : e.ctrlKey; | ||||||
|  | const isAltOrMeta = (e: KeyboardEvent) => e.altKey || (!isMac && e.metaKey); | ||||||
|  | 
 | ||||||
|  | function onKeydown(e: KeyboardEvent) { | ||||||
|  |     const isUp = e.key === "ArrowUp"; | ||||||
|  |     if (!isUp && e.key !== "ArrowDown") return; | ||||||
|  |     if (!isCtrl(e) || isAltOrMeta(e)) return; | ||||||
|  | 
 | ||||||
|  |     if (e.shiftKey) | ||||||
|  |         nextEdit(isUp); | ||||||
|  |     else | ||||||
|  |         nextReply(isUp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getNextMessage(isUp: boolean, isReply: boolean) { | ||||||
|  |     let messages: Message[] = MessageStore.getMessages(SelectedChannelStore.getChannelId())._array; | ||||||
|  |     if (!isReply) { // we are editing so only include own
 | ||||||
|  |         const meId = UserStore.getCurrentUser().id; | ||||||
|  |         messages = messages.filter(m => m.author.id === meId); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const mutate = (i: number) => isUp | ||||||
|  |         ? Math.min(messages.length - 1, i + 1) | ||||||
|  |         : Math.max(-1, i - 1); | ||||||
|  | 
 | ||||||
|  |     let i: number; | ||||||
|  |     if (isReply) | ||||||
|  |         replyIdx = i = mutate(replyIdx); | ||||||
|  |     else | ||||||
|  |         editIdx = i = mutate(editIdx); | ||||||
|  | 
 | ||||||
|  |     return i === - 1 ? undefined : messages.at(-i - 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // handle next/prev reply
 | ||||||
|  | function nextReply(isUp: boolean) { | ||||||
|  |     const message = getNextMessage(isUp, true); | ||||||
|  | 
 | ||||||
|  |     if (!message) | ||||||
|  |         return void Dispatcher.dispatch({ | ||||||
|  |             type: "DELETE_PENDING_REPLY", | ||||||
|  |             channelId: SelectedChannelStore.getChannelId(), | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |     const channel = ChannelStore.getChannel(message.channel_id); | ||||||
|  |     Dispatcher.dispatch({ | ||||||
|  |         type: "CREATE_PENDING_REPLY", | ||||||
|  |         channel, | ||||||
|  |         message, | ||||||
|  |         shouldMention: true, | ||||||
|  |         showMentionToggle: channel.guild_id !== null, | ||||||
|  |         _isQuickReply: true | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // handle next/prev edit
 | ||||||
|  | function nextEdit(isUp: boolean) { | ||||||
|  |     const message = getNextMessage(isUp, false); | ||||||
|  | 
 | ||||||
|  |     if (!message) | ||||||
|  |         Dispatcher.dispatch({ | ||||||
|  |             type: "MESSAGE_END_EDIT", | ||||||
|  |             channelId: SelectedChannelStore.getChannelId() | ||||||
|  |         }); | ||||||
|  |     else | ||||||
|  |         Dispatcher.dispatch({ | ||||||
|  |             type: "MESSAGE_START_EDIT", | ||||||
|  |             channelId: message.channel_id, | ||||||
|  |             messageId: message.id, | ||||||
|  |             content: message.content, | ||||||
|  |             _isQuickEdit: true | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | @ -1,61 +0,0 @@ | ||||||
| import definePlugin from "../utils/types"; |  | ||||||
| import { Devs } from "../utils/constants"; |  | ||||||
| import { FluxDispatcher as Dispatcher } from "../webpack/common"; |  | ||||||
| import { filters } from "../webpack"; |  | ||||||
| import { lazyWebpack } from "../utils/misc"; |  | ||||||
| 
 |  | ||||||
| const channelIdModule = lazyWebpack(filters.byProps(["getChannelId"])); |  | ||||||
| const channelModule = lazyWebpack(filters.byProps(["getChannel"])); |  | ||||||
| const messagesModule = lazyWebpack(filters.byProps(["getRawMessages"])); |  | ||||||
| 
 |  | ||||||
| export default definePlugin({ |  | ||||||
|     name: "Quickreply", |  | ||||||
|     authors: [Devs.obscurity], |  | ||||||
|     description: "Reply to messages faster (ctrl + direction)", |  | ||||||
| 
 |  | ||||||
|     start() { |  | ||||||
|         Dispatcher.subscribe("DELETE_PENDING_REPLY", onDeletePendingReply); |  | ||||||
|         document.addEventListener("keydown", onKeydown); |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     stop() { |  | ||||||
|         Dispatcher.unsubscribe("DELETE_PENDING_REPLY", onDeletePendingReply); |  | ||||||
|         document.removeEventListener("keydown", onKeydown); |  | ||||||
|     }, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| let idx = -1; |  | ||||||
| function onDeletePendingReply() { |  | ||||||
|     idx = -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function onKeydown(e: KeyboardEvent) { |  | ||||||
|     if ( |  | ||||||
|         (!e.ctrlKey && !e.metaKey) || |  | ||||||
|         (e.key !== "ArrowUp" && e.key !== "ArrowDown") |  | ||||||
|     ) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const channelId = channelIdModule.getChannelId(); |  | ||||||
|     const channel = channelModule.getChannel(channelId); |  | ||||||
|     const messages = messagesModule.getMessages(channelId).toArray().reverse(); |  | ||||||
| 
 |  | ||||||
|     if (e.key === "ArrowUp") idx += 1; |  | ||||||
|     else if (e.key === "ArrowDown") idx = Math.max(-1, idx - 1); |  | ||||||
| 
 |  | ||||||
|     if (idx > messages.length) idx = messages.length; |  | ||||||
|     if (idx < 0) { |  | ||||||
|         return void Dispatcher.dispatch({ |  | ||||||
|             type: "DELETE_PENDING_REPLY", |  | ||||||
|             channelId, |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     Dispatcher.dispatch({ |  | ||||||
|         type: "CREATE_PENDING_REPLY", |  | ||||||
|         channel: channel, |  | ||||||
|         message: messages[idx], |  | ||||||
|         showMentionToggle: channel.guild_id !== null, |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in a new issue