feat: add google-meet-transcripts-extension and caption-extension
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
const stopTranscribing = () => {
|
||||
debug("call stopTranscribing"), notificationsOff(), clearInterval(closedCaptionsAttachInterval), closedCaptionsAttachInterval = null, captionContainerChildObserver.disconnect(), captionContainerAttributeObserver.disconnect()
|
||||
},
|
||||
startTranscribing = () => {
|
||||
debug("call startTranscribing"), currentSessionIndex = null, closedCaptionsAttachInterval = setInterval(tryTo(closedCaptionsAttachLoop, "attach to captions"), 1e3), setCurrentTranscriptDetails()
|
||||
},
|
||||
toggleTranscribing = () => {
|
||||
debug("call toggleTranscribing"), isTranscribing ? stopTranscribing() : startTranscribing(), isTranscribing = !isTranscribing
|
||||
},
|
||||
turnOnCaptions = () => {
|
||||
const t = getElementWithXPathFallback(document, XPATH_TURN_ON_CAPTIONS_BUTTON, XPATH_TURN_ON_CAPTIONS_BUTTON_V20210602);
|
||||
return debug("captionsButtonOn", t), t && (t.click(), notificationsOn()), t
|
||||
},
|
||||
turnOffCaptions = () => {
|
||||
const t = getElementWithXPathFallback(document, XPATH_TURN_OFF_CAPTIONS_BUTTON, XPATH_TURN_OFF_CAPTIONS_BUTTON_V20210602);
|
||||
return debug("captionsButtonOff", t), t && (t.click(), notificationsOff()), t
|
||||
},
|
||||
turnOnCaptionNotificationsOn = () => {
|
||||
const t = document.getElementById("popup");
|
||||
t.style.backgroundColor = "#818388", t.style.color = "#292c35", t.innerHTML = "Please turn on captions", t.classList.add("show"), clearTimeout(notificationsTimeout), notificationsTimeout = setTimeout((() => {
|
||||
t.classList.remove("show")
|
||||
}), 500)
|
||||
},
|
||||
notificationsOn = () => {
|
||||
const t = document.getElementById("laxis-caption-toggle"),
|
||||
n = document.getElementById("laxis-caption-toggle-mini"),
|
||||
i = document.getElementById("captionIcon"),
|
||||
o = document.getElementById("captionIconMini");
|
||||
t.removeChild(i), n.removeChild(o);
|
||||
const e = createCaptionOnIcon(),
|
||||
c = createCaptionOnIcon();
|
||||
e.id = "captionIcon", e.style.width = "15px", e.style.height = "15px", t.appendChild(e), c.id = "captionIconMini", c.style.width = "15px", c.style.height = "15px", n.appendChild(c);
|
||||
const s = document.getElementById("popup");
|
||||
s.style.backgroundColor = "#818388", s.style.color = "#292c35", s.innerHTML = "Your caption is turned on", s.classList.add("show"), clearTimeout(notificationsTimeout), notificationsTimeout = setTimeout((() => {
|
||||
s.classList.remove("show")
|
||||
}), notificationsTimeoutDuration)
|
||||
},
|
||||
notificationsOff = () => {
|
||||
const t = document.getElementById("laxis-caption-toggle"),
|
||||
n = document.getElementById("laxis-caption-toggle-mini"),
|
||||
i = document.getElementById("captionIcon"),
|
||||
o = document.getElementById("captionIconMini");
|
||||
t.removeChild(i), n.removeChild(o);
|
||||
const e = createCaptionOffIcon(),
|
||||
c = createCaptionOffIcon();
|
||||
e.id = "captionIcon", e.style.width = "15px", e.style.height = "15px", t.appendChild(e), c.id = "captionIconMini", c.style.width = "15px", c.style.height = "15px", n.appendChild(c);
|
||||
const s = document.getElementById("popup");
|
||||
s.style.backgroundColor = "#818388", s.style.color = "#292c35", s.innerHTML = "Your caption is turned off", s.classList.add("show"), clearTimeout(notificationsTimeout), notificationsTimeout = setTimeout((() => {
|
||||
s.classList.remove("show")
|
||||
}), notificationsTimeoutDuration)
|
||||
},
|
||||
toggleCaptions = () => {
|
||||
debug("call toggleCaptions"), weTurnedCaptionsOn ? turnOffCaptions() : turnOnCaptions(), weTurnedCaptionsOn = !weTurnedCaptionsOn
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
const findCaptionsContainer = () => {
|
||||
let e = document.querySelector('div[jsname="dsyhDe"]');
|
||||
return e || (e = document.querySelector('div[jscontroller="D1tHje"] > div > div:first-child')), e && (captionContainerChildObserver.observe(e, {
|
||||
childList: !0,
|
||||
subtree: !0,
|
||||
characterData: !0
|
||||
}), captionContainerAttributeObserver.observe(e, {
|
||||
attributes: !0,
|
||||
subtree: !1,
|
||||
attributeOldValue: !0
|
||||
}), Array.from(e.children).forEach(tryTo((e => {
|
||||
updateCurrentTranscriptSession(e)
|
||||
}), "handling child node")), debug("Final CaptionsContainer", e)), e
|
||||
},
|
||||
findCaptionsContainerObsolete = () => {
|
||||
captionContainerChildObserver.disconnect(), captionContainerAttributeObserver.disconnect();
|
||||
const e = {},
|
||||
t = Array.from(document.querySelectorAll("img")).filter((e => e.src.match(/\.googleusercontent\.com\//)));
|
||||
for (let n of t) n.className in e || (e[n.className] = []), e[n.className].push(n);
|
||||
const n = [];
|
||||
for (let t of Object.values(e)) {
|
||||
let e = 0;
|
||||
for (let n of t) {
|
||||
const t = document.evaluate("..//span", n.parentElement, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE);
|
||||
let r;
|
||||
for (; r = t.iterateNext();)
|
||||
if (0 === r.children.length && r.textContent.length > 3) {
|
||||
e += 1;
|
||||
break
|
||||
}
|
||||
}
|
||||
if (e !== t.length) continue;
|
||||
let r = null;
|
||||
if (t.length >= 2) {
|
||||
const e = [...t];
|
||||
let n = null,
|
||||
o = !1;
|
||||
do {
|
||||
for (let t in e) {
|
||||
if (!e[t].parent) {
|
||||
o = !0;
|
||||
break
|
||||
}
|
||||
e[t] = e[t].parent, 0 === t ? n = e[t] : n && n !== e[t] && (n = null), debug("current", n)
|
||||
}
|
||||
} while (null === n && !1 === o);
|
||||
r = n
|
||||
} else {
|
||||
let e = t[0];
|
||||
for (; null === r && e;) e.getAttribute("jscontroller") ? r = e : e = e.parentNode
|
||||
}
|
||||
if (r) {
|
||||
const e = r?.firstChild?.firstChild?.tagName;
|
||||
debug("first grand child tag name", e);
|
||||
const t = "IMG" === e ? r : r.firstChild.firstChild;
|
||||
debug("caption container candidate", t), null !== t && n.push(t)
|
||||
}
|
||||
}
|
||||
if (1 === n.length) return captionContainerChildObserver.observe(n[0], {
|
||||
childList: !0,
|
||||
subtree: !0,
|
||||
characterData: !0
|
||||
}), captionContainerAttributeObserver.observe(n[0], {
|
||||
attributes: !0,
|
||||
subtree: !1,
|
||||
attributeOldValue: !0
|
||||
}), Array.from(n[0].children).forEach(tryTo((e => {
|
||||
updateCurrentTranscriptSession(e)
|
||||
}), "handling child node")), debug("Final CaptionsContainer", n[0]), n[0]
|
||||
},
|
||||
captionContainerChildObserver = new MutationObserver(tryTo((e => {
|
||||
for (let t of e)
|
||||
if (debug("mutation target", t.target), t.target === captionsContainer) {
|
||||
debug("update with added nodes");
|
||||
for (let e of t.addedNodes) updateCurrentTranscriptSession(e)
|
||||
} else {
|
||||
const e = Array.from(t.addedNodes).filter((e => "SPAN" === e.nodeName || "#text" === e.nodeName)),
|
||||
n = Array.from(t.removedNodes).filter((e => "SPAN" === e.nodeName || "#text" === e.nodeName));
|
||||
if (debug("addedSpansOrTexts", e), "characterData" === t.type || e.length > 0 || n.length > 0) {
|
||||
let e = t.target;
|
||||
for (; e && e.parentNode !== captionsContainer;) e = e.parentNode;
|
||||
if (!e) {
|
||||
debug("could not find root for", t.target);
|
||||
continue
|
||||
}
|
||||
if (debug("update with parent node"), e.querySelector("button")) {
|
||||
let t = Array.from(e.children),
|
||||
n = t.slice(0, t.length - 1).slice(-4);
|
||||
for (let e of n) updateCurrentTranscriptSession(e)
|
||||
} else updateCurrentTranscriptSession(e)
|
||||
}
|
||||
}
|
||||
}), "executing observer")),
|
||||
captionContainerAttributeObserver = new MutationObserver(tryTo((e => {
|
||||
for (let t of e)
|
||||
if ("style" === t.attributeName) {
|
||||
const e = t.target.getAttribute("style");
|
||||
"display: none;" === t.oldValue && "" === e && (currentSessionIndex = null)
|
||||
}
|
||||
}), "executing observer"));
|
||||
let isCaptionTurnedOn = !1;
|
||||
const closedCaptionsAttachLoop = () => {
|
||||
if (captionsContainer = findCaptionsContainer(), captionsContainer) debug("attached to closed captions"), isCaptionTurnedOn = !0, clearInterval(closedCaptionsAttachInterval);
|
||||
else if (!hasCaptionButtons) {
|
||||
if (isCaptionTurnedOn) return;
|
||||
if (getElementWithXPathFallback(document, XPATH_CAPTION_OPEN_TOAST, XPATH_CAPTION_OPEN_TOAST_V20210602)) return popup.classList.remove("show"), isCaptionTurnedOn = !0, notificationsOn(), void clearInterval(closedCaptionsAttachInterval);
|
||||
isCaptionTurnedOn || turnOnCaptionNotificationsOn()
|
||||
}
|
||||
},
|
||||
removeCaptionPanel = () => {
|
||||
// debug("start remove caption panel");
|
||||
// const e = document.querySelector('div[jscontroller="D1tHje"]');
|
||||
// debug("googleMeetCaptionsPanel", e), e && (e.style = "height: 0px", turnOffCaptions(), setTimeout((() => {
|
||||
// turnOnCaptions()
|
||||
// }), 500))
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
const parents=e=>{const t=[e];for(;e;e=e.parentNode)t.unshift(e);return t},getCommonAncestor=(e,t)=>{const n=parents(e),o=parents(t);if(n[0]===o[0])for(let e=0;e<n.length;e++)if(n[e]!==o[e])return n[e-1]},xpath=(e,t=document)=>document.evaluate(e,t,null,XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue,findButtonContainer=()=>{const e=getElementWithXPathFallback(document,XPATH_MEETING_DETAILS,XPATH_MEETING_DETAILS_V20210602),t=getElementWithXPathFallback(document,XPATH_SELECTOR_CHAT,XPATH_SELECTOR_CHAT_V20210602);return getCommonAncestor(e,t)},getElementWithXPathFallback=(e,t,n)=>xpath(t,e)||xpath(n,e),displayMenu=()=>{document.getElementById("laxis-downloadMenu").style.display="block"},dragElement=e=>{let t=0,n=0,o=0,l=0;function u(e){(e=e||window.event).preventDefault(),o=e.clientX,l=e.clientY,document.onmouseup=c,document.onmousemove=a}function a(u){(u=u||window.event).preventDefault(),t=o-u.clientX,n=l-u.clientY,o=u.clientX,l=u.clientY,e.style.top=e.offsetTop-n+"px",e.style.left=e.offsetLeft-t+"px",currentTop=e.style.top,currentRight=e.style.right}function c(){document.onmouseup=null,document.onmousemove=null}document.getElementsByName(e.id+"Header")?document.getElementsByName(e.id+"Header").forEach((e=>{e.onmousedown=u})):e.onmousedown=u};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
window.__gmt_get=t=>get(`setting.${t}`),window.__gmt_set=(t,e)=>{set(`setting.${t}`,e),syncSettings()},window.__gmt_remove=t=>{remove(`setting.${t}`),syncSettings()};const syncSettings=()=>{TRANSCRIPT_FORMAT_MEETING=getOrSet("setting.transcript-format-meeting","# $year$-$month$-$day$ $name$\n\n$text$"),TRANSCRIPT_FORMAT_SESSION_JOIN=getOrSet("setting.transcript-format-session-join","\n\n...\n\n"),TRANSCRIPT_FORMAT_SPEAKER=getOrSet("setting.transcript-format-speaker","$hour$:$minute$:$second$\n $name$: $text$"),TRANSCRIPT_FORMAT_SPEAKER_JOIN=getOrSet("setting.transcript-format-speaker-join","\n\n"),SPEAKER_NAME_MAP=getOrSet("setting.speaker-name-map",{}),DEBUG=getOrSet("setting.debug",!1)};
|
||||
@@ -0,0 +1 @@
|
||||
const makeFullKey=e=>`__laxis_${e}`,makeTranscriptKey=(...e)=>{const[t,r,o]=e,n=[`hangout_${t}`];return e.length>=2&&(n.push(`session_${r}`),e.length>=3&&n.push(`speaker_${o}`)),n.join("_")},get=e=>{const t=window.localStorage.getItem(makeFullKey(e));return"string"==typeof t||t instanceof String?(debug(e,t),JSON.parse(t)):t},set=(e,t,r=!1)=>{const o=makeFullKey(e),n=JSON.stringify(t),a=makeFullKey("rotationKeys");let s=JSON.parse(window.localStorage.getItem(a))||[],i=new Set(s);for(;;)try{window.localStorage.setItem(o,n),r&&(i.add(o),window.localStorage.setItem(a,JSON.stringify(Array.from(i))));break}catch(e){if(e instanceof DOMException&&("QuotaExceededError"===e.name||e.code===DOMException.QUOTA_EXCEEDED_ERR)){if(console.log("Local storage quota exceeded! Deleting old keys to make room for new ones. This may take a while..."),debug("Local storage quota exceeded! Deleting old keys to make room for new ones. This may take a while..."),i.size>0){for(let e=0;e<5&&i.size>0;e++){const e=i.values().next().value;i.delete(e),window.localStorage.removeItem(e)}window.localStorage.setItem(a,JSON.stringify(Array.from(i)));continue}console.error("No keys available to delete.");break}console.error("Unexpected error:",e);break}},remove=e=>{debug(`remove ${makeFullKey(e)}`),window.localStorage.removeItem(makeFullKey(e))},getOrSet=(e,t)=>{const r=get(e);return null==r?(set(e,t),t):r},increment=e=>{const t=get(e);if(null==t)return set(e,0),0;{let r=t+1;return set(e,r),r}},setSpeaker=e=>{set(makeTranscriptKey(e.transcriptId,e.sessionIndex,e.speakerIndex),{image:e.image,person:e.person,text:e.text,startedAt:e.startedAt,endedAt:e.endedAt,highlight:e.highlight},!0)},getTranscript=e=>{const t=get(makeTranscriptKey(e))||0;let r=[];const o=get(makeTranscriptKey(e,t))||0;for(let n=0;n<=o;n+=1){const o=get(makeTranscriptKey(e,t,n));if(o&&o.text&&o.text.match(/\S/g)){startTimeStored||(startTimeStored=new Date(o.startedAt),startTime=new Date(o.startedAt));const a={transcriptId:e,sessionIndex:t,speakerIndex:n,person:o.person in SPEAKER_NAME_MAP?SPEAKER_NAME_MAP[o.person]:o.person,startedAt:new Date(o.startedAt),endedAt:new Date(o.endedAt),image:o.image,text:o.text,highlight:o.highlight};r.push(a)}}return r},deleteTranscript=e=>{const t=get(makeTranscriptKey(e));for(let r=0;r<=t;r+=1){const t=get(makeTranscriptKey(e,r));for(let o=0;o<=t;o+=1)remove(makeTranscriptKey(e,r,o));remove(makeTranscriptKey(e,r))}remove(makeTranscriptKey(e)),get(makeTranscriptKey(`${e}_name`))&&remove(makeTranscriptKey(`${e}_name`));let r=get(KEY_TRANSCRIPT_IDS)||[],o=get(APPLICATION_SPEECH_IDS)||[];const n=r.indexOf(e),a=o.findIndex((t=>t.ext===e));r.splice(n,1),o.splice(a,1),debug("would set transcript to",r),debug("would set transcript pairs to",o),set(KEY_TRANSCRIPT_IDS,r),set(APPLICATION_SPEECH_IDS,o);const s=document.querySelector(`#${e}`);if(s){const e=s.parentNode;e.removeChild(s),0===e.children.length&&(e.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else debug(`transcriptNode doesn't exist for ${e}`)},deletePreviousTranscripts=()=>{let e=get(KEY_TRANSCRIPT_IDS)||[];if(e.length>1)for(let t of e)t!==currentTranscriptId&&deleteTranscript(t)};
|
||||
@@ -0,0 +1,289 @@
|
||||
const getTranscriptText = (e, t) => {
|
||||
let o = [];
|
||||
sessionList.forEach((e => {
|
||||
o.unshift(e)
|
||||
}));
|
||||
let n = "<div>",
|
||||
i = {};
|
||||
n += "<div style='font-size:20pt; color: #2F5496'>Transcripts<br></div>", o.forEach(((s, a) => {
|
||||
if (s.text && s.text.length && (0 === a || s.startedAt !== o[a - 1].startedAt)) {
|
||||
let o = "",
|
||||
a = "You" === s.person ? appUser : s.person;
|
||||
if (s.highlight.length && e && (o = s.highlight[0], s.highlight[0])) {
|
||||
let e = s.highlight[0],
|
||||
t = i[e] ? i[e] : [];
|
||||
t.push({
|
||||
text: s.text,
|
||||
time: getTimeStr(startTime, s.startedAt),
|
||||
person: a
|
||||
}), i[e] = t
|
||||
}
|
||||
if (n += "<div style='font-size:11pt'>", n = n + "<i style='color:#9e9e9e'>" + a, t && (n += ` (${getTimeStr(startTime,s.startedAt)})`), n += ": </i>", e && o.length) {
|
||||
const e = bookmarkList.find((e => e.color === o)).code;
|
||||
n += `<div style="color:${e}; display:inline">`
|
||||
}
|
||||
n += s.text, e && o.length && (n += "</div>"), n += "<br><br></div>"
|
||||
}
|
||||
})), n += "</div>";
|
||||
let s = "";
|
||||
return e && (s += "<div>", s += "<div style='font-size:20pt; color: #2F5496'>Highlights<br></div>", Object.keys(i).forEach((e => {
|
||||
let t = bookmarkList.find((t => t.color === e)),
|
||||
o = t.name,
|
||||
n = t.code;
|
||||
s += "<div>", s += `<span style="color:${n}; font-weight:bold; font-size:14pt">${o}:<br></span>`, i[e].forEach((e => {
|
||||
s += `<div style='font-size:11pt'><i style='color:#9e9e9e'>${e.person} (${e.time}): </i>${e.text}<br><br></div>`
|
||||
})), s += "</div>"
|
||||
})), s += "</div>"), `<div style='font-family:calibri'><div style='font-size:14pt'>${startTime}<br></div>` + s + n + "</div>"
|
||||
},
|
||||
Export2Txt = (e, t = "") => {
|
||||
let o = document.createElement("a"),
|
||||
n = e.replaceAll("<br>", "\n"),
|
||||
i = document.createElement("div");
|
||||
i.style.display = "none", i.innerHTML = n;
|
||||
let s = i.innerText;
|
||||
const a = new File([s], "filename"),
|
||||
d = URL.createObjectURL(a);
|
||||
return o.href = d, o.download = `${t}.txt`, document.body.appendChild(o), o.click(), document.body.removeChild(o), Promise.resolve(1)
|
||||
},
|
||||
Export2Pdf = (e, t = "") => {
|
||||
const o = window.html2pdf;
|
||||
t = t ? t + ".pdf" : `${getDefaultName()}.pdf`;
|
||||
let n = document.createElement("div");
|
||||
n.innerHTML = e, document.body.appendChild(n);
|
||||
const i = {
|
||||
margin: [8, 16, 8, 16],
|
||||
filename: `${t}.pdf`,
|
||||
enableLinks: !1,
|
||||
pagebreak: {
|
||||
avoid: ["div"],
|
||||
mode: ["css"]
|
||||
},
|
||||
image: {
|
||||
type: "jpeg",
|
||||
quality: 1
|
||||
},
|
||||
html2canvas: {
|
||||
allowTaint: !0,
|
||||
dpi: 144,
|
||||
letterRendering: !0,
|
||||
logging: !1,
|
||||
scale: 2,
|
||||
scrollX: 0,
|
||||
scrollY: 0
|
||||
}
|
||||
};
|
||||
return new Promise(((e, t) => {
|
||||
o().from(n).set(i).toPdf().get("pdf").then((e => {
|
||||
const t = e.internal.getNumberOfPages();
|
||||
for (let o = 1; o < t + 1; o++) e.setPage(o), e.setFontSize(14), e.text(`${o}/${t}`, e.internal.pageSize.getWidth() - 10, e.internal.pageSize.getHeight() - 5);
|
||||
document.body.removeChild(n)
|
||||
})).save().then((() => {
|
||||
e("Downloaded")
|
||||
})).catch((e => t(e)))
|
||||
}))
|
||||
},
|
||||
Export2Word = (e, t = "") => {
|
||||
var o = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head><meta charset='utf-8'><title>Export HTML To Doc</title></head><body>" + e + "</body></html>",
|
||||
n = new Blob(["\ufeff", o], {
|
||||
type: "application/msword"
|
||||
}),
|
||||
i = "data:application/vnd.ms-word;charset=utf-8," + encodeURIComponent(o);
|
||||
t = t ? `${t}.doc` : `${getDefaultName()}.doc`;
|
||||
var s = document.createElement("a");
|
||||
return document.body.appendChild(s), navigator.msSaveOrOpenBlob ? navigator.msSaveOrOpenBlob(n, t) : (s.href = i, s.download = t, s.click()), document.body.removeChild(s), Promise.resolve(1)
|
||||
},
|
||||
disableSaveToLaxisCloud = e => {
|
||||
const t = document.getElementById("laxis-confirm-download");
|
||||
t && (t.disabled = e, t.style.color = t.disabled ? "#999" : "");
|
||||
const o = document.getElementById("extension");
|
||||
o && (o.onchange = () => {
|
||||
t && (t.disabled = e && "app" === o.value, t.style.color = t.disabled ? "#999" : "")
|
||||
});
|
||||
const n = document.getElementById("autoSaveCheck");
|
||||
n && (n.disabled = e)
|
||||
},
|
||||
displayGoogleMeetQuota = (e, t) => {
|
||||
const o = document.getElementById("google-meet-quota");
|
||||
o && -1 !== t && 0 !== t && (e < t ? (o.innerHTML = `Autosave to Laxis cloud: ${e.toFixed(0)} / ${t.toFixed(0)} minutes. <br/> Please <span style='color: #2196f3;'>upgrade</span> to enjoy unlimited autosave.`, disableSaveToLaxisCloud(!1)) : (o.innerHTML = `Autosave to Laxis cloud: <span style='color: #E94B4B;'>${e.toFixed(0)} / ${t.toFixed(0)}</span> minutes. <br/> Please <span style='color: #2196f3;'>upgrade</span> to enjoy unlimited autosave.`, disableSaveToLaxisCloud(!0)), o.style.display = "block")
|
||||
},
|
||||
reDisplayPrompt = () => {
|
||||
const e = document.getElementById("login-prompt");
|
||||
e && (e.style.display = "block"), chrome.storage.local.remove("token")
|
||||
},
|
||||
addRemindLogin = () => {
|
||||
console.log("add login");
|
||||
const e = document.getElementById("laxis-miniPanel"),
|
||||
t = document.getElementById("laxis-expandPanel"),
|
||||
o = document.createElement("div");
|
||||
o.title = "Login to autosave notes", o.id = "laxis-remindLogin", o.style.width = "40px", o.style.height = "40px", o.classList.add("miniButtonContainer"), o.style.border = "0", o.addEventListener("click", signup), o.style.padding = "0";
|
||||
const n = createRemindLoginIcon();
|
||||
n.id = "remindLoginIcon", o.appendChild(n), n.id = "remindLoginIcon", o.style.display = "none", e.insertBefore(o, t)
|
||||
},
|
||||
reDisplayRemindLogin = () => {
|
||||
console.log("redisplay");
|
||||
const e = document.getElementById("laxis-remindLogin");
|
||||
e && (e.style.display = "block"), chrome.storage.local.remove("token")
|
||||
},
|
||||
getTopics = (e, t) => window.fetch(`${domainUrl}/api/v2/templates/${e}/topics`, t),
|
||||
Export2App = async (e, t = !1) => new Promise(((o, n) => {
|
||||
chrome.storage.local.get(["token"], (function(i) {
|
||||
if (i.token) {
|
||||
let s = document.getElementById("laxis-openDownloadMenu"),
|
||||
a = document.getElementById("laxis-download-menu-mini");
|
||||
s.classList.add("loading"), a.classList.add("loading"), window.fetch(`${domainUrl}/api/v2/templates?quick-note=true`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${i.token}`,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}).then((s => {
|
||||
200 === s.status ? s.json().then((s => {
|
||||
s.items.length ? getTopics(s.items[0].id, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${i.token}`,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}).then((a => {
|
||||
a.json().then((a => {
|
||||
const d = a.items;
|
||||
let l = [];
|
||||
if (getTranscript(currentTranscriptId).forEach((({
|
||||
image: t,
|
||||
person: o,
|
||||
text: n,
|
||||
startedAt: i,
|
||||
endedAt: s,
|
||||
highlight: a
|
||||
}) => {
|
||||
let r = [];
|
||||
if (a && e) {
|
||||
const e = bookmarkList.find((e => e.color === a[0]));
|
||||
if (e) {
|
||||
const t = d.find((t => t.color.toLowerCase() === e.code.toLowerCase()));
|
||||
t && (r = [t.id])
|
||||
}
|
||||
}
|
||||
n && l.push({
|
||||
imageUrl: t,
|
||||
person: "You" === o ? appUser : o,
|
||||
startedAt: i,
|
||||
endedAt: s || i,
|
||||
highlights: r,
|
||||
text: n
|
||||
})
|
||||
})), l.length) {
|
||||
let e = JSON.stringify({
|
||||
meetingId: currentTranscriptId,
|
||||
meetingName: document.getElementById("meeting-name").innerText,
|
||||
templateId: s.items[0].id,
|
||||
transcripts: l,
|
||||
isEnded: t
|
||||
}),
|
||||
a = {
|
||||
Authorization: `Bearer ${i.token}`,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
d = get(APPLICATION_SPEECH_IDS) || [],
|
||||
r = d.findIndex((e => e.ext === currentTranscriptId));
|
||||
if (-1 === r) window.fetch(`${domainUrl}/api/v1/speeches/google-meet`, {
|
||||
method: "POST",
|
||||
headers: a,
|
||||
body: e
|
||||
}).then((e => {
|
||||
200 === e.status ? e.json().then((e => {
|
||||
set(APPLICATION_SPEECH_IDS, [...d, {
|
||||
ext: currentTranscriptId,
|
||||
app: e.id
|
||||
}]), chrome.runtime.sendMessage({
|
||||
type: "transcriptId",
|
||||
transcriptId: e.id
|
||||
}), o(e.id)
|
||||
})) : 401 === e.status ? (e.json().then((e => {
|
||||
saveLog(`Export2App 401 fail 1 ${i.token} ${e.id} ${e.message}`)
|
||||
})), reDisplayPrompt(), n("Expired token")) : e.json().then((e => {
|
||||
n(e.message)
|
||||
}))
|
||||
})).catch((e => {
|
||||
n(e)
|
||||
}));
|
||||
else {
|
||||
let t = d[r].app;
|
||||
window.fetch(`${domainUrl}/api/v1/speeches/google-meet/${t}`, {
|
||||
method: "PUT",
|
||||
headers: a,
|
||||
body: e
|
||||
}).then((e => {
|
||||
200 === e.status ? e.json().then((() => {
|
||||
o(t)
|
||||
})) : 401 === e.status ? (e.json().then((e => {
|
||||
saveLog(`Export2App 401 fail 2 ${i.token} ${t} ${e.message}`)
|
||||
})), reDisplayPrompt(), n("Expired token")) : e.json().then((e => {
|
||||
n(e.message)
|
||||
}))
|
||||
})).catch((e => {
|
||||
n(e)
|
||||
}))
|
||||
}
|
||||
} else n("Empty transcript")
|
||||
}))
|
||||
})).catch((e => n(e))) : n("No quick note template")
|
||||
})) : 401 === s.status ? (s.json().then((e => {
|
||||
saveLog(`Export2App 401 fail 3 ${e.message} ${i.token}`)
|
||||
})), reDisplayPrompt(), n("Expired token")) : s.json().then((e => n(e.message)))
|
||||
})).catch((e => {
|
||||
n(e)
|
||||
})).finally((() => {
|
||||
s.classList.remove("loading"), a.classList.remove("loading"), s.classList.add("finishing"), a.classList.add("finishing"), setTimeout((() => {
|
||||
s.classList.remove("finishing"), a.classList.remove("finishing")
|
||||
}), 3e3)
|
||||
}))
|
||||
} else n("Not logged in")
|
||||
}))
|
||||
})), downloadTranscript = () => {
|
||||
const e = document.getElementById("meeting-name").innerText,
|
||||
t = document.getElementById("laxis-confirm-download");
|
||||
t.innerHTML = "Downloading...";
|
||||
const o = document.getElementById("highlightCheck").checked,
|
||||
n = document.getElementById("timestampCheck").checked,
|
||||
i = document.getElementById("extension").value.toString(),
|
||||
s = getTranscriptText(o, n);
|
||||
let a;
|
||||
switch (i) {
|
||||
case "pdf":
|
||||
a = () => Export2Pdf(s, e);
|
||||
break;
|
||||
case "doc":
|
||||
a = () => Export2Word(s, e);
|
||||
break;
|
||||
case "txt":
|
||||
a = () => Export2Txt(s, e);
|
||||
break;
|
||||
default:
|
||||
a = () => Export2App(o)
|
||||
}
|
||||
a().then((e => {
|
||||
"app" === i && window.open(`${domainUrl}/transcript/${e}`, "_blank")
|
||||
})).catch((e => {
|
||||
window.alert(e);
|
||||
const t = get(ERROR_SAVING) || [];
|
||||
set(ERROR_SAVING, [...t, e])
|
||||
})).finally((() => {
|
||||
t.innerHTML = "Download";
|
||||
const e = document.getElementById("laxis-downloadMenu");
|
||||
e && (e.style.display = "none")
|
||||
}))
|
||||
};
|
||||
|
||||
function saveLog(e) {
|
||||
const t = {
|
||||
message: e,
|
||||
time: (new Date).toISOString()
|
||||
};
|
||||
chrome.storage.local.get("logs", (function(e) {
|
||||
var o = structuredClone(e.logs);
|
||||
void 0 === o ? o = [t] : o.push(t), chrome.storage.local.set({
|
||||
logs: o
|
||||
})
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user