diff --git a/addon/background.js b/addon/background.js index 4cdb092..ca4256f 100644 --- a/addon/background.js +++ b/addon/background.js @@ -1,6 +1,4 @@ /* globals TestPilotGA, emailTemplates, templateMetadata */ -let selectedTemplate = templateMetadata.defaultTemplateName; - browser.runtime.onMessage.addListener((message, source) => { if (message.type === "sendEmail") { sendEmail(message.tabIds).catch((e) => { @@ -25,10 +23,8 @@ browser.runtime.onMessage.addListener((message, source) => { delete message.type; sendEvent(message); return Promise.resolve(null); - } else if (message.type === "setSelectedTemplate") { - return setSelectedTemplate(message.name); - } else if (message.type === "getSelectedTemplate") { - return Promise.resolve(selectedTemplate); + } else if (message.type === "renderTemplate") { + return renderTabs(message.tabInfo, message.selectedTemplate); } console.error("Unexpected message type:", message.type); return null; @@ -94,16 +90,14 @@ async function getTabInfo(tabIds, {wantsScreenshots, wantsReadability}) { return tabIds.map(id => tabInfo[id]); } -async function renderTabs(tabIds, templateName) { - let { wantsScreenshots, wantsReadability } = templateMetadata.getTemplate(templateName); - let tabInfo = await getTabInfo(tabIds, {wantsScreenshots, wantsReadability}); +async function renderTabs(tabInfo, templateName) { let TemplateComponent = emailTemplates[templateMetadata.getTemplate(templateName).componentName]; if (!TemplateComponent) { throw new Error(`No component found for template: ${templateName}`); } let html = emailTemplates.renderEmail(tabInfo, TemplateComponent); let subject = emailTemplates.renderSubject(tabInfo); - return { html, tabInfo, subject }; + return { html, subject }; } async function sendEmail(tabIds) { @@ -126,22 +120,25 @@ async function sendEmail(tabIds) { loginInterrupt(); } }, 1000); - let { html, tabInfo, subject } = await renderTabs(tabIds, selectedTemplate); + let tabInfo = await getTabInfo(tabIds, {wantsScreenshots: true, wantsReadability: true}); + await browser.tabs.executeScript(newTab.id, { + file: "templateMetadata.js", + runAt: "document_start", + }); await browser.tabs.executeScript(newTab.id, { file: "set-html-email.js", runAt: "document_start", }); await browser.tabs.sendMessage(newTab.id, { - type: "setHtml", - html, - subject, + type: "sendTabInfo", thisTabId: newTab.id, tabInfo }); } async function copyTabHtml(tabIds) { - let { html } = await renderTabs(tabIds, selectedTemplate); + let tabInfo = await getTabInfo(tabIds, {wantsScreenshots: false, wantsReadability: false}); + let { html } = await renderTabs(tabInfo, "just_links"); copyHtmlToClipboard(html); } @@ -195,23 +192,3 @@ async function closeManyTabs(composeTabId, otherTabInfo) { } await browser.tabs.remove(toClose); } - -async function setSelectedTemplate(newName) { - selectedTemplate = newName; - await browser.storage.local.set({selectedTemplate: newName}); -} - -async function init() { - let result = await browser.storage.local.get(["selectedTemplate"]); - if (result && result.selectedTemplate) { - try { - // Checks that the template really exists: - templateMetadata.getTemplate(result.selectedTemplate); - selectedTemplate = result.selectedTemplate; - } catch (e) { - console.error("Could not set template", result.selectedTemplate, "to:", String(e)); - } - } -} - -init(); diff --git a/addon/gmail-iframe.html b/addon/gmail-iframe.html index 71602c6..fb2abaa 100644 --- a/addon/gmail-iframe.html +++ b/addon/gmail-iframe.html @@ -73,6 +73,15 @@ box-shadow: 0 2px 8px rgba(12, 12, 13, 0.1); } + .big-container { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.8); + } + #loading-container { width: 100%; height: 100%; @@ -213,5 +222,16 @@ + + diff --git a/addon/popup.jsx b/addon/popup.jsx index b9722d8..77806b5 100644 --- a/addon/popup.jsx +++ b/addon/popup.jsx @@ -2,8 +2,6 @@ let activeTabLi; let selected = new Map(); -let isChoosingTemplate = false; -let selectedTemplate = templateMetadata.defaultTemplateName; const LOGIN_ERROR_TIME = 90 * 1000; // 90 seconds class Tab extends React.Component { @@ -78,7 +76,6 @@ class Popup extends React.Component { this.allCheckbox = allCheckbox} type="checkbox" id="allCheckbox" onChange={this.onClickCheckAll.bind(this)} /> Select All -
@@ -143,10 +140,6 @@ class Popup extends React.Component { }, 300); } - chooseTemplate() { - isChoosingTemplate = true; - render(); - } } class LoginError extends React.Component { @@ -158,47 +151,6 @@ class LoginError extends React.Component { } } -class TemplateChooser extends React.Component { - render() { - let templates = templateMetadata.metadata.map(template => { - return ; - }); - return
- -
- -
-
; - } - - onCancel() { - isChoosingTemplate = false; - render(); - } -} - -class TemplateItem extends React.Component { - render() { - let className = ""; - if (this.props.selected) { - className += " selected"; - } - return
  • - -
  • ; - } - - selectTemplate() { - setSelectedTemplate(this.props.name); - isChoosingTemplate = false; - render(); - } -} - async function render(firstRun) { let tabs = await browser.tabs.query({currentWindow: true}); if (firstRun) { @@ -214,12 +166,7 @@ async function render(firstRun) { if (Date.now() - showLoginError > LOGIN_ERROR_TIME) { showLoginError = 0; } - let page; - if (isChoosingTemplate) { - page = ; - } else { - page = ; - } + let page = ; ReactDOM.render(page, document.getElementById("panel")); if (firstRun) { activeTabLi.scrollIntoView({ @@ -296,13 +243,7 @@ for (let eventName of ["onAttached", "onCreated", "onDetached", "onMoved", "onUp browser.tabs.onRemoved.addListener(renderWithDelay); -async function setSelectedTemplate(name) { - selectedTemplate = name; - await browser.runtime.sendMessage({type: "setSelectedTemplate", name}); -} - async function init() { - selectedTemplate = await browser.runtime.sendMessage({type: "getSelectedTemplate"}); render(true); } diff --git a/addon/set-html-email.js b/addon/set-html-email.js index f3c122d..dab8d4d 100644 --- a/addon/set-html-email.js +++ b/addon/set-html-email.js @@ -1,20 +1,18 @@ -/* globals cloneInto */ +/* globals cloneInto, templateMetadata */ browser.runtime.onMessage.addListener((message) => { try { thisTabId = message.thisTabId; - closeTabInfo = message.tabInfo; - setSubject(message.subject); - setHtml(message.html); + tabInfo = message.tabInfo; } catch (e) { - console.error("Unable to setHtml:", String(e), e.stack); + console.error("Error getting tabInfo:", String(e), e.stack); throw e; } }); let completed = false; let thisTabId; -let closeTabInfo; +let tabInfo; window.addEventListener("beforeunload", () => { if (completed) { @@ -28,7 +26,6 @@ window.addEventListener("beforeunload", () => { browser.runtime.sendMessage({ type: "sendFailed" }); - console.error("beforeunload"); }); function setSubject(subject) { @@ -116,7 +113,7 @@ function showCloseButtons() { let done = iframeDocument.querySelector("#done"); let doneMsg = iframeDocument.querySelector("#done-message"); let closeAllTabs = iframeDocument.querySelector("#close-all-tabs"); - let numTabs = closeTabInfo.length; + let numTabs = tabInfo.length; if (numTabs === 1) { closeAllTabs.textContent = closeAllTabs.getAttribute("data-one-tab"); doneMsg.textContent = doneMsg.getAttribute("data-one-tab"); @@ -133,7 +130,7 @@ function showCloseButtons() { closeAllTabs.addEventListener("click", async () => { await browser.runtime.sendMessage({ type: "closeTabs", - closeTabInfo, + closeTabInfo: tabInfo, composeTabId: thisTabId }); }); @@ -143,6 +140,39 @@ function showLoading() { showIframe("#loading-container"); } +function showTemplateSelector() { + showIframe("#choose-template"); + let cancel = iframeDocument.querySelector("#choose-template-cancel"); + cancel.addEventListener("click", async () => { + completed = true; + await browser.runtime.sendMessage({ + type: "closeComposeTab", + tabId: thisTabId, + }); + }); + let elTemplate = iframeDocument.querySelector(".template-template"); + for (let template of templateMetadata.metadata) { + let instance = elTemplate.cloneNode(true); + instance.style.display = ""; + instance.classList.remove("template-template"); + for (let el of instance.querySelectorAll("*[data-substitute]")) { + el.textContent = template[el.getAttribute("data-substitute")]; + el.removeAttribute("data-substitute"); + } + instance.addEventListener("click", async () => { + showLoading(); + let { html, subject } = await browser.runtime.sendMessage({ + type: "renderTemplate", + selectedTemplate: template.name, + tabInfo, + }); + setSubject(subject); + setHtml(html); + }); + cancel.parentNode.insertBefore(instance, cancel); + } +} + let iframe = null; let initPromise; let iframeDocument = null; @@ -182,7 +212,7 @@ function createIframe() { } function showIframe(container) { - let containers = ["#loading-container", "#done-container"]; + let containers = ["#loading-container", "#done-container", "#choose-template"]; if (!containers.includes(container)) { throw new Error(`Unexpected container: ${container}`); } @@ -203,5 +233,5 @@ function hideIframe() { createIframe(); initPromise.then(() => { - showLoading(); + showTemplateSelector(); });