thunderbird-patch-review
Easy-to-use patch review interface for Thunderbird
Contribute: ~marcc/thunderbird-review-plugin@lists.sr.ht
git clone git://mccd.space/thunderbird-patch-review
| Log | Files | Refs | README | LICENSE |
options.js (2815B)
1 "use strict";
2
3 const tbody = document.querySelector("#mappings tbody");
4
5 function addRow(match = "", repo = "") {
6 const tr = document.createElement("tr");
7
8 const matchTd = document.createElement("td");
9 matchTd.className = "match";
10 const matchInput = document.createElement("input");
11 matchInput.type = "text";
12 matchInput.placeholder = "list-id or sender contains…";
13 matchInput.value = match;
14 matchTd.appendChild(matchInput);
15
16 const repoTd = document.createElement("td");
17 const repoInput = document.createElement("input");
18 repoInput.type = "text";
19 repoInput.placeholder = "/absolute/path/to/repo";
20 repoInput.value = repo;
21 repoTd.appendChild(repoInput);
22
23 const browseTd = document.createElement("td");
24 browseTd.className = "remove";
25 const browseBtn = document.createElement("button");
26 browseBtn.textContent = "…";
27 browseBtn.title = "Browse for the repository directory";
28 browseBtn.addEventListener("click", async () => {
29 const response = await messenger.runtime.sendMessage({
30 type: "pick-repo",
31 start: repoInput.value.trim(),
32 });
33 if (response && response.ok && response.output) {
34 repoInput.value = response.output.replace(/(.)\/$/, "$1");
35 }
36 });
37 browseTd.appendChild(browseBtn);
38
39 const removeTd = document.createElement("td");
40 removeTd.className = "remove";
41 const removeBtn = document.createElement("button");
42 removeBtn.textContent = "✕";
43 removeBtn.title = "Remove";
44 removeBtn.addEventListener("click", () => tr.remove());
45 removeTd.appendChild(removeBtn);
46
47 tr.append(matchTd, repoTd, browseTd, removeTd);
48 tbody.appendChild(tr);
49 }
50
51 async function load() {
52 const found = await messenger.storage.local.get("config");
53 const config = Object.assign({ editor: "", strategy: "am3", mappings: [] }, found.config);
54 document.querySelector("#editor").value = config.editor;
55 document.querySelector("#strategy").value = config.strategy;
56 for (const mapping of config.mappings) {
57 addRow(mapping.match, mapping.repo);
58 }
59 if (!config.mappings.length) {
60 addRow();
61 }
62 }
63
64 document.querySelector("#add").addEventListener("click", () => addRow());
65
66 document.querySelector("#save").addEventListener("click", async () => {
67 const mappings = [...tbody.querySelectorAll("tr")]
68 .map((tr) => {
69 const [match, repo] = [...tr.querySelectorAll("input")].map((el) => el.value.trim());
70 return { match, repo };
71 })
72 .filter((mapping) => mapping.match && mapping.repo);
73
74 await messenger.storage.local.set({
75 config: {
76 editor: document.querySelector("#editor").value.trim(),
77 strategy: document.querySelector("#strategy").value,
78 mappings,
79 },
80 });
81 const saved = document.querySelector("#saved");
82 saved.hidden = false;
83 setTimeout(() => (saved.hidden = true), 1500);
84 });
85
86 load();