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