-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuser-stats-badge.user.js
More file actions
153 lines (127 loc) · 5.23 KB
/
user-stats-badge.user.js
File metadata and controls
153 lines (127 loc) · 5.23 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
148
149
150
151
152
153
// ==UserScript==
// @name TRMNL User Stats Badge
// @namespace https://github.com/ExcuseMi/trmnl-userscripts
// @version 1.4.5
// @description Display user install/fork/connection badges on the right side of the Private Plugin header
// @author ExcuseMi
// @match https://trmnl.com/*
// @icon https://raw.githubusercontent.com/ExcuseMi/trmnl-userscripts/refs/heads/main/images/trmnl.svg
// @downloadURL https://raw.githubusercontent.com/ExcuseMi/trmnl-userscripts/main/user-stats-badge.user.js
// @updateURL https://raw.githubusercontent.com/ExcuseMi/trmnl-userscripts/main/user-stats-badge.user.js
// @grant none
// ==/UserScript==
(function() {
'use strict';
const LOG_PREFIX = '[TRMNL User Stats Badge]';
const log = (...args) => console.log(LOG_PREFIX, ...args);
const warn = (...args) => console.warn(LOG_PREFIX, ...args);
const BADGE_ID = 'trmnl-user-stats-badge';
const TARGET_PATH = '/plugin_settings';
const TARGET_PARAM = 'keyname=private_plugin';
function isDarkMode() {
return document.documentElement.classList.contains('dark');
}
function badgeColorParams() {
return isDarkMode()
? ''
: '&glyph=white&color=000000&labelColor=77767B';
}
function updateBadgeColors() {
const img = document.querySelector(`#${BADGE_ID} img[data-badge-base]`);
if (!img) return;
img.src = `${img.dataset.badgeBase}${badgeColorParams()}`;
}
new MutationObserver(updateBadgeColors)
.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
function isTargetPage() {
return location.pathname === TARGET_PATH && location.search.includes(TARGET_PARAM);
}
function onNavigate() {
if (!isTargetPage()) return;
log('On target page. URL:', location.href);
waitForHeader();
}
log('Script loaded. readyState:', document.readyState);
document.addEventListener('turbo:load', () => {
log('turbo:load fired.');
onNavigate();
});
document.addEventListener('turbo:frame-load', () => {
log('turbo:frame-load fired.');
if (!isTargetPage()) return;
trySetup();
});
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
log('DOMContentLoaded fired.');
onNavigate();
});
} else {
onNavigate();
}
function waitForHeader() {
if (document.getElementById(BADGE_ID)) {
log('Badge already present, skipping.');
return;
}
if (trySetup()) return;
const observeTarget = document.querySelector('.flex-grow.sticky.top-14') || document.documentElement;
log('Header not ready, observing:', observeTarget.tagName, observeTarget.className.slice(0, 60));
const observer = new MutationObserver(() => {
if (trySetup()) {
observer.disconnect();
}
});
observer.observe(observeTarget, { childList: true, subtree: true });
}
function trySetup() {
if (document.getElementById(BADGE_ID)) {
log('Badge already present, skipping duplicate setup.');
return true;
}
const stickyHeader = document.querySelector('.flex-grow.sticky.top-14');
if (!stickyHeader) {
log('Sticky header not found yet (.flex-grow.sticky.top-14).');
return false;
}
const rightContainer = stickyHeader.querySelector('.shrink-0.flex.justify-end.items-end.gap-3');
if (!rightContainer) {
log('Right container not found yet (.shrink-0.flex.justify-end.items-end.gap-3).');
return false;
}
const userId = extractUserIdFromIntercom();
if (!userId) {
warn('Could not extract user ID from Intercom script.');
return false;
}
log('Setting up badge for user ID:', userId);
const badgeContainer = document.createElement('div');
badgeContainer.id = BADGE_ID;
badgeContainer.className = 'flex items-center gap-2 mr-2';
const img = document.createElement('img');
const badgeBase = `https://trmnl-badges.gohk.xyz/badge/connections?userId=${userId}&pretty`;
img.dataset.badgeBase = badgeBase;
img.src = `${badgeBase}&${badgeColorParams()}`;
img.alt = 'Connections';
img.className = 'h-9 inline-block';
badgeContainer.appendChild(img);
const importBtn = Array.from(rightContainer.children).find(el =>
el.textContent.trim().toLowerCase().includes('import'));
if (importBtn) {
rightContainer.insertBefore(badgeContainer, importBtn);
} else {
rightContainer.prepend(badgeContainer);
}
log('Badge inserted successfully.');
return true;
}
function extractUserIdFromIntercom() {
const intercomScript = document.getElementById('IntercomSettingsScriptTag');
if (!intercomScript) {
log('IntercomSettingsScriptTag not found.');
return null;
}
const match = intercomScript.innerHTML.match(/"user_id":\s*(\d+)/);
return match ? match[1] : null;
}
})();