-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsidepanel.js
More file actions
147 lines (129 loc) · 4.97 KB
/
Copy pathsidepanel.js
File metadata and controls
147 lines (129 loc) · 4.97 KB
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
const startButton = document.getElementById("startButton");
const resetButton = document.getElementById("resetButton");
const profileLabel = document.getElementById("profileLabel");
const statusBadge = document.getElementById("statusBadge");
const updatedLabel = document.getElementById("updatedLabel");
const noteLabel = document.getElementById("note");
const strategyValue = document.getElementById("strategyValue");
const phaseValue = document.getElementById("phaseValue");
const pagesValue = document.getElementById("pagesValue");
const lastSeenValue = document.getElementById("lastSeenValue");
const stopReasonValue = document.getElementById("stopReasonValue");
const followersCount = document.getElementById("followersCount");
const followingCount = document.getElementById("followingCount");
const diffCount = document.getElementById("diffCount");
const followersMeta = document.getElementById("followersMeta");
const followingMeta = document.getElementById("followingMeta");
const diffMeta = document.getElementById("diffMeta");
const followersList = document.getElementById("followersList");
const followingList = document.getElementById("followingList");
const diffList = document.getElementById("diffList");
startButton.addEventListener("click", async () => {
startButton.disabled = true;
try {
const response = await chrome.runtime.sendMessage({ type: "START_ANALYSIS" });
if (!response?.ok) {
throw new Error(response?.error || "Failed to start analysis.");
}
renderState(response.state);
} catch (error) {
renderError(error.message);
}
});
resetButton.addEventListener("click", async () => {
const response = await chrome.runtime.sendMessage({ type: "RESET_ANALYSIS" });
renderState(response.state);
});
document.querySelectorAll("[data-copy-target]").forEach((button) => {
button.addEventListener("click", async () => {
const target = button.dataset.copyTarget;
const state = await loadState();
const text = (state?.[target] || []).join("\n");
await navigator.clipboard.writeText(text);
button.textContent = "Copied";
window.setTimeout(() => {
button.textContent = "Copy";
}, 1200);
});
});
chrome.runtime.onMessage.addListener((message) => {
if (message?.type === "STATE_UPDATED" && message.state) {
renderState(message.state);
}
});
void init();
async function init() {
const state = await loadState();
renderState(state);
}
async function loadState() {
const response = await chrome.runtime.sendMessage({ type: "GET_ANALYSIS_STATE" });
if (!response?.ok) {
throw new Error(response?.error || "Failed to load extension state.");
}
return response.state;
}
function renderState(state = {}) {
profileLabel.textContent = state.profileUsername ? `@${state.profileUsername}` : "No profile selected";
statusBadge.textContent = titleCase(state.status || "idle");
statusBadge.className = `badge ${state.status || "idle"}`;
updatedLabel.textContent = formatDate(state.updatedAt);
noteLabel.textContent = state.error || state.note || "Ready.";
strategyValue.textContent = titleCase(state.strategy || "-");
phaseValue.textContent = titleCase(state.phase || "-");
pagesValue.textContent = String(state.pagesFetched || 0);
lastSeenValue.textContent = state.lastSeenUsername || "-";
stopReasonValue.textContent = state.stopReason || "No stop reason yet.";
followersCount.textContent = formatCount(state.counts?.followers);
followingCount.textContent = formatCount(state.counts?.following);
diffCount.textContent = formatCount(state.counts?.notFollowingBack);
renderLog(followersList, followersMeta, state.followers, "Followers will appear here.");
renderLog(followingList, followingMeta, state.following, "Following will appear here.");
renderLog(diffList, diffMeta, state.notFollowingBack, "The comparison result will appear here.");
startButton.disabled = state.status === "starting" || state.status === "running";
}
function renderLog(container, meta, values = [], emptyText) {
const lines = Array.isArray(values) ? values : [];
meta.textContent = `${lines.length} username${lines.length === 1 ? "" : "s"}`;
if (!lines.length) {
container.textContent = emptyText;
container.classList.add("empty");
return;
}
container.textContent = lines.join("\n");
container.classList.remove("empty");
}
function renderError(message) {
renderState({
status: "error",
note: message,
error: message,
counts: {
followers: 0,
following: 0,
notFollowingBack: 0
},
followers: [],
following: [],
notFollowingBack: []
});
}
function formatCount(value) {
return new Intl.NumberFormat().format(Number(value || 0));
}
function formatDate(value) {
if (!value) {
return "No run yet";
}
return new Date(value).toLocaleString([], {
dateStyle: "medium",
timeStyle: "short"
});
}
function titleCase(value) {
return String(value)
.split(/[\s_-]+/)
.filter(Boolean)
.map((segment) => segment[0].toUpperCase() + segment.slice(1))
.join(" ");
}