/* * Vencord, a Discord client mod * Copyright (c) 2025 Vendicated and contributors * SPDX-License-Identifier: GPL-3.0-or-later */ import { NavContextMenuPatchCallback } from "@api/ContextMenu"; import { EquicordDevs } from "@utils/constants"; import definePlugin from "@utils/types"; import { Menu, NavigationRouter, RestAPI, Toasts, UserStore } from "@webpack/common"; async function findLastMessageFromUser(guildId: string, channelId: string, userId: string) { try { const res = await RestAPI.get({ url: `/guilds/${guildId}/messages/search?author_id=${userId}&channel_id=${channelId}&sort_by=timestamp&sort_order=desc&offset=0` }); const allMessages = res.body.messages?.flat() || []; const newestMessage = allMessages.find(msg => msg && msg.id); if (newestMessage) return newestMessage.id; Toasts.show({ type: Toasts.Type.FAILURE, message: "Couldn't find any recent messages from this user.", id: Toasts.genId() }); return null; } catch (error) { console.error("Error finding last message:", error); Toasts.show({ type: Toasts.Type.FAILURE, message: "Failed to find messages. Check console for details.", id: Toasts.genId() }); return null; } } async function jumpToLastActive(channel: any, targetUserId?: string) { try { if (!channel) { Toasts.show({ type: Toasts.Type.FAILURE, message: "Channel information not available.", id: Toasts.genId() }); return; } const guildId = channel.guild_id !== null ? channel.guild_id : "@me"; const channelId = channel.id; let userId: string; if (targetUserId) { userId = targetUserId; } else { const currentUser = UserStore.getCurrentUser(); userId = currentUser.id; } const messageId = await findLastMessageFromUser(guildId, channelId, userId); if (messageId) { const url = `/channels/${guildId}/${channelId}/${messageId}`; NavigationRouter.transitionTo(url); } } catch (error) { console.error("Error in jumpToLastActive:", error); Toasts.show({ type: Toasts.Type.FAILURE, message: "Failed to jump to message. Check console for details.", id: Toasts.genId() }); } } const ChannelContextMenuPatch: NavContextMenuPatchCallback = (children, { channel }) => { children.push( Your Last Message} icon={LastActiveIcon} action={() => { jumpToLastActive(channel); }} /> ); }; const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { user, channel }) => { if (!channel || !user?.id) return; children.push( User's Last Message} icon={UserLastActiveIcon} action={() => { jumpToLastActive(channel, user.id); }} /> ); }; export function UserLastActiveIcon() { return ( ); } export function LastActiveIcon() { return ( ); } export default definePlugin({ name: "LastActive", description: "A plugin to jump to last active message from yourself or another user in a channel/server.", tags: ["Chat", "Utility"], authors: [EquicordDevs.Crxa], contextMenus: { "channel-context": ChannelContextMenuPatch, "user-context": UserContextMenuPatch, "thread-context": ChannelContextMenuPatch } });