AIWindowMenu.sys.mjs (3847B)
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 import { AIWindow } from "moz-src:///browser/components/aiwindow/ui/modules/AIWindow.sys.mjs"; 7 8 const lazy = {}; 9 ChromeUtils.defineESModuleGetters(lazy, { 10 BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs", 11 URILoadingHelper: "resource:///modules/URILoadingHelper.sys.mjs", 12 }); 13 14 const MAX_RECENT_CHATS = 4; 15 16 /** 17 * Adds the AI Window menuitems to the app menu 18 */ 19 export class AIWindowMenu { 20 constructor() {} 21 22 /** 23 * Adds the AI menu bar menuitems 24 * 25 * @param {Event} event - Event from clicking the History app menu item 26 * @param {Window} win - Window reference 27 */ 28 async addMenuitems(event, win) { 29 this.#addChatsMenuitem(win, event.target); 30 await this.#addRecentChats(win, event.target); 31 } 32 33 #addChatsMenuitem(win, menu) { 34 this.#removeChatsMenuitem(menu); 35 36 if (!AIWindow.isAIWindowActiveAndEnabled(win)) { 37 return; 38 } 39 40 this.#addChatsMenuitemToHistory(menu); 41 } 42 43 #removeChatsMenuitem(menu) { 44 const chatsMenuitem = menu.querySelector("#chatsHistoryMenu"); 45 chatsMenuitem.hidden = true; 46 } 47 48 #addChatsMenuitemToHistory(menu) { 49 const chatsMenuitem = menu.querySelector("#chatsHistoryMenu"); 50 chatsMenuitem.hidden = false; 51 } 52 53 async #addRecentChats(win, menu) { 54 this.#removeChatsMenuitems(menu); 55 56 if (!AIWindow.isAIWindowActiveAndEnabled(win)) { 57 return; 58 } 59 60 const items = 61 await AIWindow.chatStore.findRecentConversations(MAX_RECENT_CHATS); 62 63 if (!items.length) { 64 return; 65 } 66 67 this.#addRecentChatsMenuitemHeader(menu); 68 this.#addRecentChatMenuitems(items, win); 69 } 70 71 #removeChatsMenuitems(menu) { 72 const separator = menu.querySelector("#startChatHistorySeparator"); 73 separator.hidden = true; 74 75 const startingElement = menu.querySelector("#recentChatsHeader"); 76 startingElement.hidden = true; 77 78 let next = startingElement?.nextElementSibling; 79 80 while (next && next.hasAttribute && next.hasAttribute("data-conv-id")) { 81 const toRemove = next; 82 next = next.nextSibling; 83 toRemove.remove(); 84 } 85 } 86 87 #addRecentChatsMenuitemHeader(menu) { 88 const separator = menu.querySelector("#startChatHistorySeparator"); 89 separator.hidden = false; 90 91 const chatsHeader = menu.querySelector("#recentChatsHeader"); 92 chatsHeader.hidden = false; 93 } 94 95 #addRecentChatMenuitems(items, win) { 96 const document = win.document; 97 const chatsHeader = document.getElementById("recentChatsHeader"); 98 99 while (items.length) { 100 const item = items.pop(); 101 const menuItem = document.createXULElement("menuitem"); 102 menuItem.classList.add("recent-chat-item"); 103 menuItem.setAttribute("label", item.title); 104 menuItem.setAttribute("data-conv-id", item.id); 105 menuItem.addEventListener("command", this.#onRecentChatMenuitemClick); 106 107 chatsHeader.insertAdjacentElement("afterend", menuItem); 108 } 109 } 110 111 async #onRecentChatMenuitemClick(event) { 112 const convId = event.target.getAttribute("data-conv-id"); 113 const conversation = await AIWindow.chatStore.findConversationById(convId); 114 115 if (!conversation) { 116 return; 117 } 118 119 newBrowserTabUrl += `#convId/${convId}`; 120 121 const win = event.target.ownerGlobal; 122 let newBrowserTabUrl = win.BROWSER_NEW_TAB_URL; 123 const site = conversation.getMostRecentPageVisited(); 124 if (site) { 125 newBrowserTabUrl += `#convId/${convId}/site/${site}`; 126 } 127 128 let where = lazy.BrowserUtils.whereToOpenLink(event); 129 if (where === "current") { 130 where = "tab"; 131 } 132 133 lazy.URILoadingHelper.openTrustedLinkIn(win, newBrowserTabUrl, where); 134 } 135 }