-
-
Notifications
You must be signed in to change notification settings - Fork 15
/
bulkDeleteConversations.js
176 lines (144 loc) · 4.92 KB
/
bulkDeleteConversations.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
console.log("bulkDeleteConversations.js loaded");
async function bulkDeleteConversations() {
const selectedConversations = getSelectedConversations();
if (selectedConversations.length === 0) {
console.log("No conversations to delete.");
removeAllCheckboxes();
chrome.runtime.sendMessage({ action: "deleteComplete" });
return;
}
console.log("Selected Conversations:", selectedConversations.length);
// Send analytics event
sendEventAsync("delete", selectedConversations.length);
// Track how many conversations were actually processed
let processedCount = 0;
let skippedCount = 0;
for (let i = 0; i < selectedConversations.length; i++) {
const result = await deleteConversation(selectedConversations[i]);
if (result) {
processedCount++;
} else {
skippedCount++;
}
// Calculate progress based on total attempts
const progress = Math.round(((i + 1) / selectedConversations.length) * 100);
chrome.runtime.sendMessage({
action: "updateProgress",
buttonId: "bulk-delete",
progress: progress,
});
}
console.log(
`Processed ${processedCount} conversations, skipped ${skippedCount} conversations`
);
chrome.runtime.sendMessage({
action: "operationComplete",
buttonId: "bulk-delete",
});
}
function getSelectedConversations() {
return [...document.querySelectorAll(Selectors.conversationsCheckbox)];
}
function removeAllCheckboxes() {
const allCheckboxes = document.querySelectorAll(`.${CHECKBOX_CLASS}`);
allCheckboxes.forEach((checkbox) => checkbox.remove());
}
async function deleteConversation(checkbox) {
await delay(100);
const conversationElement = checkbox.parentElement;
console.log("conversationElement", conversationElement);
// Look for hoverable element within the conversation element
const hoverableDiv = conversationElement.querySelector(
"div.can-hover\\:group-hover\\:flex"
);
if (!hoverableDiv) {
console.log("Skipping conversation - no hoverable element found");
// Show notification to user
const title =
conversationElement.querySelector(Selectors.TITLE_SELECTOR)
?.textContent || "this conversation";
alert(`Unable to delete unread conversation: "${title}".`);
return false;
}
const hoverEvent = new MouseEvent("mouseover", {
view: window,
bubbles: true,
cancelable: true,
});
console.log("1. Hovering over conversation...", conversationElement);
conversationElement.dispatchEvent(hoverEvent);
await delay(200);
// Try to find the three dot button
try {
const threeDotButton = await waitForElement(
Selectors.threeDotButton,
conversationElement.parentElement,
1000 // Reduced timeout for non-hoverable items
);
console.log("2. Clicking three dot button...", threeDotButton);
const pointerDownEvent = new PointerEvent("pointerdown", {
bubbles: true,
cancelable: true,
pointerType: "mouse",
});
threeDotButton.dispatchEvent(pointerDownEvent);
await delay(300);
const deleteButton = await waitForDeleteButton();
if (deleteButton) {
console.log("3. Clicking delete button...", deleteButton);
deleteButton.click();
const confirmButton = await waitForElement(Selectors.confirmDeleteButton);
if (confirmButton) {
console.log("4. Clicking confirm button...");
confirmButton.click();
await waitForElementToDisappear(Selectors.confirmDeleteButton);
return true;
}
}
} catch (error) {
console.log("Could not complete deletion process:", error);
return false;
}
return false;
}
async function waitForDeleteButton(parent = document, timeout = 2000) {
const selector = 'div[role="menuitem"]';
const textContent = "Delete";
const startedAt = Date.now();
while (Date.now() - startedAt < timeout) {
const elements = parent.querySelectorAll(selector);
const element = Array.from(elements).find(
(el) =>
el.textContent.trim() === textContent ||
el.querySelector(".text-token-text-error")
);
if (element) return element;
await delay(100);
}
return null;
}
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function waitForElement(selector, parent = document, timeout = 2000) {
const startedAt = Date.now();
while (Date.now() - startedAt < timeout) {
const element = parent.querySelector(selector);
if (element) return element;
await delay(100);
}
throw new Error(
`Element ${selector} not found within ${timeout}ms in the specified parent`
);
}
async function waitForElementToDisappear(selector, timeout = 2000) {
const startedAt = Date.now();
while (Date.now() - startedAt < timeout) {
const element = document.querySelector(selector);
if (!element) return;
await delay(100);
}
throw new Error(`Element ${selector} did not disappear within ${timeout}ms`);
}
// Start the bulk delete process
bulkDeleteConversations();