Skip to content

Commit 5cd4c66

Browse files
authored
Merge pull request #80 from vivek-nexus/3.2.12
3.2.12
2 parents d4ce24a + 5a40e3a commit 5cd4c66

7 files changed

Lines changed: 112 additions & 53 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Simple Google Meet transcripts. Private and open source.
55
66
![marquee-large](/assets/marquee-large.png)
77

8-
Extension status: 🟢 OPERATIONAL (v3.2.11)
8+
Extension status: 🟢 OPERATIONAL (v3.2.12)
99

1010
<br />
1111
<br />

extension-unpacked.zip

1.14 KB
Binary file not shown.

extension/content.js

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -302,38 +302,66 @@ function transcriptMutationCallback(mutationsList) {
302302
mutationsList.forEach((mutation) => {
303303
try {
304304
if (mutation.type === "characterData") {
305-
const currentPersonName = mutation.target.parentElement?.previousSibling?.textContent
306-
const currentTranscriptText = mutation.target.parentElement?.textContent
307-
308-
if (currentPersonName && currentTranscriptText) {
309-
// Attempt to dim down the transcript
310-
mutation.target.parentElement?.parentElement?.setAttribute("style", "opacity:0.2")
311-
312-
// Starting fresh in a meeting
313-
if (!transcriptTargetBuffer) {
314-
transcriptTargetBuffer = mutation.target.parentElement
315-
personNameBuffer = currentPersonName
316-
timestampBuffer = new Date().toISOString()
317-
transcriptTextBuffer = currentTranscriptText
318-
}
319-
// Some prior transcript buffer exists
320-
else {
321-
// New transcript UI block
322-
if (transcriptTargetBuffer !== mutation.target.parentElement) {
323-
// Push previous transcript block
324-
pushBufferToTranscript()
325-
326-
// Update buffers for next mutation and store transcript block timestamp
327-
transcriptTargetBuffer = mutation.target.parentElement
305+
const mutationTargetElement = mutation.target.parentElement
306+
const transcriptUIBlocks = [...mutationTargetElement?.parentElement?.parentElement?.children || []]
307+
const isLastButSecondElement = transcriptUIBlocks[transcriptUIBlocks.length - 3] === mutationTargetElement?.parentElement ? true : false
308+
309+
// Pick up only last second element (the last and last but one are non transcript elements), since Meet mutates previous blocks to make minor corrections. Picking them up leads to repetitive transcript blocks in the result.
310+
if (isLastButSecondElement) {
311+
// Attempt to dim down the current transcript
312+
[...transcriptUIBlocks[transcriptUIBlocks.length - 3].children].forEach((item) => {
313+
item.setAttribute("style", "opacity:0.2")
314+
})
315+
316+
const currentPersonName = mutationTargetElement?.previousSibling?.textContent
317+
const currentTranscriptText = mutationTargetElement?.textContent
318+
319+
if (currentPersonName && currentTranscriptText) {
320+
// Starting fresh in a meeting or resume from no active transcript
321+
if (transcriptTextBuffer === "") {
328322
personNameBuffer = currentPersonName
329323
timestampBuffer = new Date().toISOString()
330324
transcriptTextBuffer = currentTranscriptText
331325
}
332-
// Same transcript UI block being appended
326+
// Some prior transcript buffer exists
333327
else {
334-
// Update buffer for next mutation
335-
transcriptTextBuffer = currentTranscriptText
328+
// New person started speaking
329+
if (personNameBuffer !== currentPersonName) {
330+
// Push previous person's transcript as a block
331+
pushBufferToTranscript()
332+
333+
// Update buffers for next mutation and store transcript block timestamp
334+
personNameBuffer = currentPersonName
335+
timestampBuffer = new Date().toISOString()
336+
transcriptTextBuffer = currentTranscriptText
337+
}
338+
// Same person speaking more
339+
else {
340+
// When the same person speaks for more than 30 min (approx), Meet drops very long transcript for current person and starts over, which is detected by current transcript string being significantly smaller than the previous one
341+
if ((currentTranscriptText.length - transcriptTextBuffer.length) < -250) {
342+
// Push the long transcript
343+
pushBufferToTranscript()
344+
345+
// Store transcript block timestamp for next transcript block of same person
346+
timestampBuffer = new Date().toISOString()
347+
}
348+
349+
// Update buffers for next mutation
350+
transcriptTextBuffer = currentTranscriptText
351+
}
352+
}
353+
}
354+
// No people found in transcript DOM
355+
else {
356+
// No transcript yet or the last person stopped speaking(and no one has started speaking next)
357+
console.log("No active transcript")
358+
// Push data in the buffer variables to the transcript array, but avoid pushing blank ones.
359+
if ((personNameBuffer !== "") && (transcriptTextBuffer !== "")) {
360+
pushBufferToTranscript()
336361
}
362+
// Update buffers for the next person in the next mutation
363+
personNameBuffer = ""
364+
transcriptTextBuffer = ""
337365
}
338366
}
339367
}
@@ -433,7 +461,7 @@ function pushBufferToTranscript() {
433461
function pushUniqueChatBlock(chatBlock) {
434462
const isExisting = chatMessages.some(item =>
435463
(item.personName === chatBlock.personName) &&
436-
(chatBlock.chatMessageText === item.chatMessageText)
464+
(item.chatMessageText === chatBlock.chatMessageText)
437465
)
438466
if (!isExisting) {
439467
console.log(chatBlock)

extension/icons/delete.svg

Lines changed: 1 addition & 0 deletions
Loading

extension/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "TranscripTonic",
4-
"version": "3.2.11",
4+
"version": "3.2.12",
55
"description": "Simple Google Meet transcripts. Private and open source.",
66
"action": {
77
"default_icon": "icon.png",

extension/meetings.html

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@
233233
align-items: center;
234234
}
235235

236+
#meetings-table-container {
237+
overflow-x: auto;
238+
}
239+
236240
table {
237241
width: 100%;
238242
border-collapse: collapse;
@@ -267,24 +271,17 @@
267271
font-weight: bold
268272
}
269273

270-
.download-button {
274+
.download-button,
275+
.delete-button,
276+
.post-button {
271277
background: transparent;
272278
color: #2A9ACA;
273279
border: none;
274280
padding: 0;
275281
display: flex;
276282
flex-direction: column;
277283
justify-content: end;
278-
}
279-
280-
.post-button {
281-
background: transparent;
282-
color: #2A9ACA;
283-
border: 1px solid #2A9ACA;
284-
padding: 0.25rem 0.5rem;
285-
display: flex;
286-
gap: 0.25rem;
287-
align-items: center;
284+
font-size: smaller;
288285
}
289286

290287
.card-heading {
@@ -367,7 +364,7 @@ <h2>Last 10 meetings</h2>
367364
<th>Meeting software</th>
368365
<th>Meeting start time and duration</th>
369366
<th>Webhook status</th>
370-
<th>Actions</th>
367+
<th></th>
371368
</tr>
372369
</thead>
373370
<tbody id="meetings-table">
@@ -376,7 +373,8 @@ <h2>Last 10 meetings</h2>
376373
</table>
377374
</div>
378375
<button id="show-all" style="display: none;">Show
379-
all</button>
376+
all
377+
</button>
380378
</section>
381379

382380
<section id="webhooks">

extension/meetings.js

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ function loadMeetings() {
203203
const row = document.createElement("tr")
204204
row.innerHTML = `
205205
<td>
206+
<div contenteditable="true" class="meeting-title" data-index="${i}" style="text-decoration: underline #a0a0a0; text-underline-offset: 6px;" title="Rename">
206207
${meeting.meetingTitle || meeting.title || "Google Meet call"}
208+
</div>
207209
</td>
208210
<td>
209211
${meeting.meetingSoftware ? meeting.meetingSoftware : ""}
@@ -226,23 +228,36 @@ function loadMeetings() {
226228
)()}
227229
</td>
228230
<td>
229-
<div style="min-width: 128px; display: flex; gap: 1rem;">
230-
<button class="download-button" data-index="${i}">
231-
<img src="./icons/download.svg" alt="Download this meeting transcript">
231+
<div style="display: flex; gap: 1rem; justify-content: end">
232+
<button class="download-button" data-index="${i}" title="Download" aria-label="Download this meeting transcript">
233+
<img src="./icons/download.svg" alt="">
232234
</button>
233-
<button class="post-button" data-index="${i}">
234-
${meeting.webhookPostStatus === "new" ? `Post` : `Repost`}
235-
<img src="./icons/webhook.svg" alt="" width="16px">
235+
<button class="post-button" data-index="${i}" title="${meeting.webhookPostStatus === "new" ? `Post webhook` : `Repost webhook`}" aria-label="${meeting.webhookPostStatus === "new" ? `` : ``}">
236+
${meeting.webhookPostStatus === "new" ? `` : ``}
237+
<img src="./icons/webhook.svg" alt="">
238+
</button>
239+
&nbsp;
240+
<button class="delete-button" data-index="${i}" title="Delete" aria-label="Delete this meeting">
241+
<img src="./icons/delete.svg" alt="">
236242
</button>
237243
</div>
238244
</td>
239245
`
240246
meetingsTable.appendChild(row)
241247

242-
const meetingsTableContainer = document.querySelector("#meetings-table-container")
243-
if (!isMeetingsTableExpanded && meetingsTableContainer && (meetingsTableContainer.clientHeight > 320)) {
244-
meetingsTableContainer?.classList.add("fade-mask")
245-
document.querySelector("#show-all")?.setAttribute("style", "display: block")
248+
// Add event listener to meeting title input
249+
const meetingTitleInput = row.querySelector(".meeting-title")
250+
if (meetingTitleInput instanceof HTMLDivElement) {
251+
meetingTitleInput.addEventListener("blur", function () {
252+
const updatedMeeting = /** @type {Meeting} */ {
253+
...meeting,
254+
meetingTitle: meetingTitleInput.innerText
255+
}
256+
meetings[i] = updatedMeeting
257+
chrome.storage.local.set({ meetings: meetings }, function () {
258+
console.log("Meeting title updated")
259+
})
260+
})
246261
}
247262

248263
// Add event listener to the webhook post button
@@ -258,7 +273,6 @@ function loadMeetings() {
258273
}
259274
chrome.runtime.sendMessage(message, (responseUntyped) => {
260275
const response = /** @type {ExtensionResponse} */ (responseUntyped)
261-
loadMeetings()
262276
if (!response.success) {
263277
alert("Could not download transcript")
264278
const parsedError = /** @type {ErrorObject} */ (response.message)
@@ -314,6 +328,24 @@ function loadMeetings() {
314328
})
315329
})
316330
}
331+
332+
// Add event listener to the meeting delete button
333+
const deleteButton = row.querySelector(".delete-button")
334+
if (deleteButton instanceof HTMLButtonElement) {
335+
deleteButton.addEventListener("click", function () {
336+
if (confirm("Delete this meeting?")) {
337+
meetings.splice(i, 1)
338+
chrome.storage.local.set({ meetings: meetings }, function () {
339+
console.log("Meeting title updated")
340+
})
341+
}
342+
})
343+
}
344+
}
345+
const meetingsTableContainer = document.querySelector("#meetings-table-container")
346+
if (!isMeetingsTableExpanded && meetingsTableContainer && (meetingsTableContainer.clientHeight > 280)) {
347+
meetingsTableContainer?.classList.add("fade-mask")
348+
document.querySelector("#show-all")?.setAttribute("style", "display: block")
317349
}
318350
}
319351
else {

0 commit comments

Comments
 (0)