founders-break/public/js/share.js

125 lines
4.7 KiB
JavaScript

/* Sharing for /flyer.
There is no "share protocol" as such. What exists is the Web Share API, which
on a phone opens the real OS share sheet (Messages, Mail, WhatsApp, Instagram,
AirDrop) and is the only thing that reaches apps a web page cannot link to.
Desktop browsers mostly do not have it, so every channel also has a plain URL
fallback, and copy-to-clipboard underneath that. */
(function () {
"use strict";
var S = window.__fbShare;
if (!S) return;
function track(type, data) {
if (!S.siteId) return;
try {
fetch("https://api.corben.world/analytics/events", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
site_id: S.siteId,
events: [{ event_type: type, page_path: location.pathname, event_data: data || {}, ts: Date.now() }],
}),
keepalive: true,
}).catch(function () {});
} catch (e) {}
}
var msg = S.text + " " + S.url;
var enc = encodeURIComponent;
/* ── Plain links, so every one of these works with JS half-broken ── */
var links = {
// "&body=" after "?&" is the form that works on both iOS and Android.
"share-sms": "sms:?&body=" + enc(msg),
"share-email": "mailto:?subject=" + enc(S.title) + "&body=" + enc(S.text + "\n\n" + S.url + "\n\nPrintable flyer: " + S.pdf),
"share-whatsapp": "https://wa.me/?text=" + enc(msg),
"share-x": "https://twitter.com/intent/tweet?text=" + enc(S.text) + "&url=" + enc(S.url),
"share-linkedin": "https://www.linkedin.com/sharing/share-offsite/?url=" + enc(S.url),
"share-facebook": "https://www.facebook.com/sharer/sharer.php?u=" + enc(S.url),
};
Object.keys(links).forEach(function (id) {
var el = document.getElementById(id);
if (el) el.href = links[id];
});
/* ── The OS share sheet, where it exists ── */
var nativeBtn = document.getElementById("share-native");
if (nativeBtn && navigator.share) {
nativeBtn.hidden = false;
nativeBtn.addEventListener("click", function () {
shareNative();
});
}
function shareNative() {
var payload = { title: S.title, text: S.text, url: S.url };
// Sharing the PDF itself is much better than a link when it is going into a
// group chat, but canShare({files}) is the only honest way to ask, and it
// needs the file fetched first. Fall back to the link if anything about
// that fails rather than leaving the button dead.
if (navigator.canShare) {
fetch(S.pdf)
.then(function (r) { if (!r.ok) throw new Error("pdf " + r.status); return r.blob(); })
.then(function (blob) {
var file = new File([blob], "founders-break-flyer.pdf", { type: "application/pdf" });
if (!navigator.canShare({ files: [file] })) throw new Error("files unsupported");
return navigator.share({ title: S.title, text: S.text, files: [file] })
.then(function () { track("share", { channel: "native-file" }); });
})
.catch(function () {
navigator.share(payload)
.then(function () { track("share", { channel: "native-link" }); })
.catch(function () {});
});
return;
}
navigator.share(payload)
.then(function () { track("share", { channel: "native-link" }); })
.catch(function () {});
}
/* ── Copy the link ── */
var copyBtn = document.getElementById("copy-link");
var copyLabel = document.getElementById("copy-label");
if (copyBtn) {
copyBtn.addEventListener("click", function () {
var done = function (ok) {
copyLabel.textContent = ok ? "Copied" : "Press Cmd C to copy";
copyBtn.classList.toggle("is-copied", ok);
track("share", { channel: "copy", ok: ok });
setTimeout(function () {
copyLabel.textContent = "Copy the link";
copyBtn.classList.remove("is-copied");
}, 2200);
};
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(S.url).then(function () { done(true); }, function () { selectFallback(done); });
} else {
selectFallback(done);
}
});
}
// Clipboard API is blocked in some in-app browsers. Selecting the text at
// least lets someone copy it by hand instead of hitting a dead button.
function selectFallback(done) {
var t = document.createElement("textarea");
t.value = S.url;
t.setAttribute("readonly", "");
t.style.cssText = "position:fixed;top:0;left:0;opacity:0";
document.body.appendChild(t);
t.select();
var ok = false;
try { ok = document.execCommand("copy"); } catch (e) {}
document.body.removeChild(t);
done(ok);
}
/* Channel clicks are already caught by the site tracker via data-track, so
nothing extra is needed for those. */
})();