зеркало из https://github.com/mozilla/email-tabs.git
Merge pull request #100 from mozilla/interstitial-template-select
Start #41, put in an interstitial template selector
This commit is contained in:
Коммит
b376196e63
|
@ -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();
|
||||
|
|
|
@ -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 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="choose-template" class="container big-container" style="display: none">
|
||||
<div class="template-template" style="display: none">
|
||||
<button>
|
||||
Use <span data-substitute="title"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="choose-template-container" class="card-container">
|
||||
<button id="choose-template-cancel">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -137,13 +137,13 @@ supply a favicon */
|
|||
|
||||
.feedback-link {
|
||||
font-size: 11px;
|
||||
color: #4A4A4F;
|
||||
color: #4a4a4f;
|
||||
letter-spacing: -0.08px;
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
.feedback-link a {
|
||||
color: #0A84FF;
|
||||
color: #0a84ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
|||
<input checked={allChecked} ref={allCheckbox => this.allCheckbox = allCheckbox} type="checkbox" id="allCheckbox" onChange={this.onClickCheckAll.bind(this)} />
|
||||
Select All
|
||||
</label>
|
||||
<button onClick={this.chooseTemplate.bind(this)}>Change template ({selectedTemplate})</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="separator"></div>
|
||||
|
@ -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 <TemplateItem key={template.name} selected={template.name === selectedTemplate} {...template} />;
|
||||
});
|
||||
return <div>
|
||||
<ul>
|
||||
{ templates }
|
||||
</ul>
|
||||
<footer className="panel-footer toggle-enabled">
|
||||
<button onClick={this.onCancel.bind(this)}>
|
||||
Cancel
|
||||
</button>
|
||||
</footer>
|
||||
</div>;
|
||||
}
|
||||
|
||||
onCancel() {
|
||||
isChoosingTemplate = false;
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
class TemplateItem extends React.Component {
|
||||
render() {
|
||||
let className = "";
|
||||
if (this.props.selected) {
|
||||
className += " selected";
|
||||
}
|
||||
return <li className={className}>
|
||||
<button onClick={this.selectTemplate.bind(this)}>{this.props.title}</button>
|
||||
</li>;
|
||||
}
|
||||
|
||||
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 = <TemplateChooser />;
|
||||
} else {
|
||||
page = <Popup selected={selected} tabs={tabs} showLoginError={showLoginError} />;
|
||||
}
|
||||
let page = <Popup selected={selected} tabs={tabs} showLoginError={showLoginError} />;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче