mirror of
https://github.com/suitenumerique/meet.git
synced 2026-07-27 20:29:09 +00:00
Compare commits
3 Commits
csp-addin
...
thunderbird
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d7f2957f9 | |||
| d83d3ccc18 | |||
| 52a9a583e8 |
Generated
+4169
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "thunderbird",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "web-ext run",
|
||||||
|
"lint": "web-ext lint --source-dir=./src"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"web-ext": "^10.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { buildMeetingMessage } from "./lib/meeting-message.js";
|
||||||
|
|
||||||
|
console.log("[meeting-link] background loaded at", new Date().toISOString());
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
console.log("[meeting-link] browser.calendar exists?", !!browser.calendar);
|
||||||
|
if (browser.calendar) {
|
||||||
|
console.log("[meeting-link] calendar namespace keys:",
|
||||||
|
Object.keys(browser.calendar));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try the most basic read call — list configured calendars.
|
||||||
|
// The exact method name varies between experiment versions; we'll
|
||||||
|
// try the common one first.
|
||||||
|
if (browser.calendar.calendars?.query) {
|
||||||
|
const calendars = await browser.calendar.calendars.query({});
|
||||||
|
console.log("[meeting-link] calendars found:", calendars.length, calendars);
|
||||||
|
} else {
|
||||||
|
console.warn("[meeting-link] calendars.query not present — namespace shape:",
|
||||||
|
browser.calendar);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[meeting-link] calendar probe failed:", err);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Hardcoded for Spike 1. Spike 2 replaces this with a fetch() to your API.
|
||||||
|
const STUB_MEETING_DATA = {
|
||||||
|
url: "https://meet.example.com/m/abc-123-xyz",
|
||||||
|
telephony: {
|
||||||
|
phone_number: "+33123456789",
|
||||||
|
pin_code: "1234567890",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
browser.runtime.onMessage.addListener(async (msg) => {
|
||||||
|
if (msg?.type === "GET_MEETING_MESSAGE") {
|
||||||
|
try {
|
||||||
|
const built = buildMeetingMessage(STUB_MEETING_DATA);
|
||||||
|
return { ok: true, ...built };
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[meeting-link] build failed", err);
|
||||||
|
return { ok: false, error: String(err.message || err) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "Meeting Link (dev)",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Spike 0 — verifying the dev loop",
|
||||||
|
"browser_specific_settings": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "meeting-link-dev@yourcompany.example",
|
||||||
|
"strict_min_version": "128.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"scripts": ["background.js"],
|
||||||
|
"type": "module"
|
||||||
|
},
|
||||||
|
"compose_action": {
|
||||||
|
"default_title": "Insert meeting link",
|
||||||
|
"default_popup": "popup/popup.html",
|
||||||
|
"default_icon": "icons/icon-32.png"
|
||||||
|
},
|
||||||
|
"permissions": ["compose"],
|
||||||
|
"experiment_apis": {
|
||||||
|
"calendar_provider": {
|
||||||
|
"schema": "experiments/calendar/schema/calendar-provider.json",
|
||||||
|
"parent": {
|
||||||
|
"scopes": ["addon_parent"],
|
||||||
|
"paths": [["calendar", "provider"]],
|
||||||
|
"script": "experiments/calendar/parent/ext-calendar-provider.js",
|
||||||
|
"events": ["startup"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"calendar_calendars": {
|
||||||
|
"schema": "experiments/calendar/schema/calendar-calendars.json",
|
||||||
|
"parent": {
|
||||||
|
"scopes": ["addon_parent"],
|
||||||
|
"paths": [["calendar", "calendars"]],
|
||||||
|
"script": "experiments/calendar/parent/ext-calendar-calendars.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Meeting link</title>
|
||||||
|
<style>
|
||||||
|
body { font: 13px system-ui; padding: 12px; min-width: 240px; margin: 0; }
|
||||||
|
button { font: inherit; padding: 6px 12px; cursor: pointer; }
|
||||||
|
#status { margin-top: 8px; color: #555; min-height: 1.2em; white-space: pre-wrap; }
|
||||||
|
#status.error { color: #b00020; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<button id="insert">Insert meeting link</button>
|
||||||
|
<div id="status"></div>
|
||||||
|
<script src="popup.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
const insertBtn = document.getElementById("insert");
|
||||||
|
const statusEl = document.getElementById("status");
|
||||||
|
|
||||||
|
function setStatus(text, isError = false) {
|
||||||
|
statusEl.textContent = text;
|
||||||
|
statusEl.classList.toggle("error", isError);
|
||||||
|
}
|
||||||
|
|
||||||
|
insertBtn.addEventListener("click", async () => {
|
||||||
|
insertBtn.disabled = true;
|
||||||
|
setStatus("Generating link…");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Find the compose tab this popup belongs to.
|
||||||
|
// A compose_action popup is anchored to a compose window, so the
|
||||||
|
// "active tab in the current window" is the compose tab itself.
|
||||||
|
const [composeTab] = await browser.tabs.query({
|
||||||
|
active: true,
|
||||||
|
currentWindow: true,
|
||||||
|
});
|
||||||
|
if (!composeTab) throw new Error("No compose tab found");
|
||||||
|
|
||||||
|
// 2. Read the current compose state — we need to know if we're
|
||||||
|
// in HTML mode or plain-text mode, and we need the existing body
|
||||||
|
// so we can append rather than overwrite.
|
||||||
|
const details = await browser.compose.getComposeDetails(composeTab.id);
|
||||||
|
|
||||||
|
// 3. Ask the background to produce the meeting message.
|
||||||
|
const reply = await browser.runtime.sendMessage({
|
||||||
|
type: "GET_MEETING_MESSAGE",
|
||||||
|
});
|
||||||
|
if (!reply?.ok) throw new Error(reply?.error || "Background error");
|
||||||
|
|
||||||
|
// 4. Append to the existing body in the right format.
|
||||||
|
if (details.isPlainText) {
|
||||||
|
const newBody = (details.plainTextBody || "") + "\n\n" + reply.text;
|
||||||
|
await browser.compose.setComposeDetails(composeTab.id, {
|
||||||
|
plainTextBody: newBody,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const newBody = appendHtmlBeforeBodyEnd(details.body || "", reply.html);
|
||||||
|
await browser.compose.setComposeDetails(composeTab.id, {
|
||||||
|
body: newBody,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus("Inserted ✓");
|
||||||
|
setTimeout(() => window.close(), 600);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[meeting-link] popup insert failed", err);
|
||||||
|
setStatus("Failed: " + (err.message || err), true);
|
||||||
|
insertBtn.disabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append HTML right before </body>, or fall back to concatenation if no
|
||||||
|
* </body> tag is present (Thunderbird's compose body is usually a full
|
||||||
|
* HTML document, but be defensive).
|
||||||
|
*/
|
||||||
|
function appendHtmlBeforeBodyEnd(currentHtml, fragment) {
|
||||||
|
const idx = currentHtml.toLowerCase().lastIndexOf("</body>");
|
||||||
|
if (idx === -1) return currentHtml + fragment;
|
||||||
|
return currentHtml.slice(0, idx) + fragment + currentHtml.slice(idx);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// web-ext-config.cjs
|
||||||
|
const os = require("os");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
function thunderbirdBinary() {
|
||||||
|
if (process.env.WEB_EXT_FIREFOX) return process.env.WEB_EXT_FIREFOX;
|
||||||
|
switch (process.platform) {
|
||||||
|
case "darwin":
|
||||||
|
return "/Applications/Thunderbird Beta.app/Contents/MacOS/thunderbird";
|
||||||
|
case "linux":
|
||||||
|
return "/usr/bin/thunderbird"; // adjust to your install
|
||||||
|
case "win32":
|
||||||
|
return "C:\\Program Files\\Mozilla Thunderbird\\thunderbird.exe";
|
||||||
|
default:
|
||||||
|
throw new Error("Unsupported platform: " + process.platform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
sourceDir: "./src",
|
||||||
|
artifactsDir: "./web-ext-artifacts",
|
||||||
|
run: {
|
||||||
|
firefox: thunderbirdBinary(),
|
||||||
|
firefoxProfile: path.join(os.homedir(), ".thunderbird-dev-profile"),
|
||||||
|
profileCreateIfMissing: true,
|
||||||
|
keepProfileChanges: true,
|
||||||
|
browserConsole: true,
|
||||||
|
},
|
||||||
|
ignoreFiles: ["package-lock.json", "web-ext-config.cjs", "*.md"],
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user