antigravity-rtl-patcher 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +2 -2
- package/package.json +1 -1
- package/payload/preload-inject.js +277 -129
package/bin/cli.js
CHANGED
|
@@ -5,13 +5,13 @@ const chalk = require('chalk');
|
|
|
5
5
|
const { patch, restore, status } = require('../src/patcher');
|
|
6
6
|
|
|
7
7
|
const BANNER = `
|
|
8
|
-
${chalk.cyan('Antigravity Smart RTL Patcher')} ${chalk.gray('v2.
|
|
8
|
+
${chalk.cyan('Antigravity Smart RTL Patcher')} ${chalk.gray('v2.3.0')}
|
|
9
9
|
`;
|
|
10
10
|
|
|
11
11
|
program
|
|
12
12
|
.name('agy-rtl')
|
|
13
13
|
.description('RTL patcher for Antigravity')
|
|
14
|
-
.version('2.
|
|
14
|
+
.version('2.3.0');
|
|
15
15
|
|
|
16
16
|
program
|
|
17
17
|
.command('patch')
|
package/package.json
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AGY RTL — Preload Injection Snippet
|
|
3
3
|
* Appended to Antigravity's preload.js at patch time.
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Only applies RTL direction to individual text elements containing
|
|
6
|
+
* Persian/Arabic/Hebrew characters. Does NOT change the app layout.
|
|
5
7
|
*
|
|
6
8
|
* MARKER: __AGY_RTL_INJECTED__
|
|
7
9
|
*/
|
|
8
10
|
(function _agyRtlPreloadInit() {
|
|
9
|
-
// Only run in renderer context
|
|
10
11
|
if (typeof document === 'undefined') {
|
|
11
|
-
// We're in the preload context before DOM exists.
|
|
12
|
-
// Schedule injection for when the page actually loads.
|
|
13
12
|
const { webFrame } = require('electron');
|
|
14
|
-
|
|
15
13
|
webFrame.executeJavaScript(`(${_agyRtlRendererMain.toString()})();`);
|
|
16
14
|
return;
|
|
17
15
|
}
|
|
@@ -21,91 +19,216 @@
|
|
|
21
19
|
function _agyRtlRendererMain() {
|
|
22
20
|
'use strict';
|
|
23
21
|
|
|
24
|
-
// Prevent double injection
|
|
25
22
|
if (window.__AGY_RTL_LOADED__) return;
|
|
26
23
|
window.__AGY_RTL_LOADED__ = true;
|
|
27
24
|
|
|
28
|
-
// ───
|
|
25
|
+
// ─── Config ──────────────────────────────────────────────
|
|
29
26
|
var STORAGE_KEY = 'agy-rtl-enabled';
|
|
30
27
|
var PANEL_ID = 'agy-rtl-panel';
|
|
31
28
|
var TOGGLE_BTN_ID = 'agy-rtl-toggle-btn';
|
|
32
29
|
var STATUS_ICON_ID = 'agy-rtl-status-icon';
|
|
33
30
|
var GITHUB_URL = 'https://github.com/VaFa1726/antigravity-rtl-patcher';
|
|
31
|
+
var PROCESSED_ATTR = 'data-agy-rtl';
|
|
34
32
|
|
|
35
|
-
// RTL detection
|
|
36
33
|
var RTL_REGEX = /[\u0591-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC]/;
|
|
37
34
|
var RTL_CHAR_REGEX = /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/g;
|
|
38
|
-
var MIN_RTL_RATIO = 0.
|
|
39
|
-
var PROCESSED_ATTR = 'data-agy-rtl';
|
|
40
|
-
|
|
41
|
-
var TARGET_SELECTORS = [
|
|
42
|
-
'p', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'td', 'th',
|
|
43
|
-
'.chat-response-content p', '.chat-response-content li',
|
|
44
|
-
'.chat-response-content h1', '.chat-response-content h2',
|
|
45
|
-
'.chat-response-content h3', '.chat-response-content h4',
|
|
46
|
-
'.chat-response-content blockquote',
|
|
47
|
-
'.markdown-body p', '.markdown-body li',
|
|
48
|
-
'.markdown-body h1', '.markdown-body h2',
|
|
49
|
-
'.markdown-body h3', '.markdown-body blockquote',
|
|
50
|
-
'.rendered-markdown p', '.rendered-markdown li',
|
|
51
|
-
'.rendered-markdown h1', '.rendered-markdown h2',
|
|
52
|
-
'.rendered-markdown h3', '.rendered-markdown blockquote',
|
|
53
|
-
'.monaco-hover-content p', '.suggest-details p',
|
|
54
|
-
'.notification-toast-container p',
|
|
55
|
-
].join(', ');
|
|
35
|
+
var MIN_RTL_RATIO = 0.25;
|
|
56
36
|
|
|
57
37
|
// ─── State ───────────────────────────────────────────────
|
|
58
38
|
var isEnabled = getStoredState();
|
|
59
39
|
var observer = null;
|
|
60
40
|
var panelVisible = false;
|
|
41
|
+
var hoverTimeout = null;
|
|
61
42
|
|
|
62
43
|
// ─── CSS ─────────────────────────────────────────────────
|
|
63
|
-
var CSS =
|
|
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
|
-
|
|
44
|
+
var CSS = `
|
|
45
|
+
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
|
|
46
|
+
|
|
47
|
+
/* RTL styling — applied per-element, NOT globally */
|
|
48
|
+
[${PROCESSED_ATTR}="true"] {
|
|
49
|
+
direction: rtl !important;
|
|
50
|
+
text-align: right !important;
|
|
51
|
+
unicode-bidi: plaintext !important;
|
|
52
|
+
font-family: 'Vazirmatn', system-ui, -apple-system, 'Segoe UI', sans-serif !important;
|
|
53
|
+
line-height: 1.8 !important;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Keep code LTR inside RTL blocks */
|
|
57
|
+
[${PROCESSED_ATTR}="true"] code,
|
|
58
|
+
[${PROCESSED_ATTR}="true"] pre {
|
|
59
|
+
direction: ltr !important;
|
|
60
|
+
text-align: left !important;
|
|
61
|
+
unicode-bidi: isolate !important;
|
|
62
|
+
font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', Consolas, monospace !important;
|
|
63
|
+
display: inline-block;
|
|
64
|
+
}
|
|
65
|
+
[${PROCESSED_ATTR}="true"] code {
|
|
66
|
+
margin: 0 3px;
|
|
67
|
+
padding: 1px 5px;
|
|
68
|
+
border-radius: 3px;
|
|
69
|
+
}
|
|
70
|
+
[${PROCESSED_ATTR}="true"] li {
|
|
71
|
+
list-style-position: inside;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* === Status Bar Icon === */
|
|
75
|
+
.agy-rtl-status-icon {
|
|
76
|
+
position: fixed;
|
|
77
|
+
bottom: 6px;
|
|
78
|
+
right: 16px;
|
|
79
|
+
z-index: 99999;
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
justify-content: center;
|
|
83
|
+
gap: 6px;
|
|
84
|
+
height: 28px;
|
|
85
|
+
padding: 0 12px;
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
border-radius: 14px;
|
|
88
|
+
user-select: none;
|
|
89
|
+
-webkit-user-select: none;
|
|
90
|
+
transition: background .2s, opacity .2s, box-shadow .2s;
|
|
91
|
+
opacity: .6;
|
|
92
|
+
font-family: -apple-system, 'Segoe UI', system-ui, sans-serif;
|
|
93
|
+
font-size: 12px;
|
|
94
|
+
font-weight: 600;
|
|
95
|
+
letter-spacing: .03em;
|
|
96
|
+
color: #888;
|
|
97
|
+
background: rgba(128,128,128,.08);
|
|
98
|
+
}
|
|
99
|
+
.agy-rtl-status-icon:hover {
|
|
100
|
+
opacity: 1;
|
|
101
|
+
background: rgba(128,128,128,.15);
|
|
102
|
+
color: #aaa;
|
|
103
|
+
}
|
|
104
|
+
.agy-rtl-status-icon.active {
|
|
105
|
+
color: #5ba0d6;
|
|
106
|
+
opacity: .85;
|
|
107
|
+
background: rgba(91,160,214,.08);
|
|
108
|
+
}
|
|
109
|
+
.agy-rtl-status-icon.active:hover {
|
|
110
|
+
opacity: 1;
|
|
111
|
+
background: rgba(91,160,214,.15);
|
|
112
|
+
box-shadow: 0 0 12px rgba(91,160,214,.12);
|
|
113
|
+
}
|
|
114
|
+
.agy-rtl-status-icon svg {
|
|
115
|
+
flex-shrink: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* === Panel === */
|
|
119
|
+
.agy-rtl-panel {
|
|
120
|
+
position: fixed;
|
|
121
|
+
z-index: 100000;
|
|
122
|
+
width: 260px;
|
|
123
|
+
background: #1e1e1e;
|
|
124
|
+
border: 1px solid #333;
|
|
125
|
+
border-radius: 10px;
|
|
126
|
+
box-shadow: 0 12px 40px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.04);
|
|
127
|
+
padding: 0;
|
|
128
|
+
opacity: 0;
|
|
129
|
+
visibility: hidden;
|
|
130
|
+
transform: translateY(6px);
|
|
131
|
+
transition: opacity .15s ease, transform .15s ease, visibility .15s ease;
|
|
132
|
+
font-family: -apple-system, 'Segoe UI', system-ui, sans-serif;
|
|
133
|
+
font-size: 13px;
|
|
134
|
+
color: #ccc;
|
|
135
|
+
overflow: hidden;
|
|
136
|
+
direction: ltr !important;
|
|
137
|
+
text-align: left !important;
|
|
138
|
+
}
|
|
139
|
+
.agy-rtl-panel.visible {
|
|
140
|
+
opacity: 1;
|
|
141
|
+
visibility: visible;
|
|
142
|
+
transform: translateY(0);
|
|
143
|
+
}
|
|
144
|
+
.agy-rtl-panel-header {
|
|
145
|
+
padding: 14px 16px 12px;
|
|
146
|
+
background: rgba(255,255,255,.03);
|
|
147
|
+
border-bottom: 1px solid #2a2a2a;
|
|
148
|
+
}
|
|
149
|
+
.agy-rtl-panel-title {
|
|
150
|
+
font-size: 13px;
|
|
151
|
+
font-weight: 600;
|
|
152
|
+
color: #e0e0e0;
|
|
153
|
+
}
|
|
154
|
+
.agy-rtl-panel-body {
|
|
155
|
+
padding: 8px 16px 12px;
|
|
156
|
+
}
|
|
157
|
+
.agy-rtl-panel-row {
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
justify-content: space-between;
|
|
161
|
+
padding: 8px 0;
|
|
162
|
+
}
|
|
163
|
+
.agy-rtl-panel-label {
|
|
164
|
+
font-size: 13px;
|
|
165
|
+
color: #b0b0b0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Toggle */
|
|
169
|
+
.agy-rtl-switch {
|
|
170
|
+
position: relative;
|
|
171
|
+
display: inline-block;
|
|
172
|
+
width: 36px;
|
|
173
|
+
height: 20px;
|
|
174
|
+
cursor: pointer;
|
|
175
|
+
flex-shrink: 0;
|
|
176
|
+
}
|
|
177
|
+
.agy-rtl-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
|
|
178
|
+
.agy-rtl-slider {
|
|
179
|
+
position: absolute;
|
|
180
|
+
inset: 0;
|
|
181
|
+
background: #444;
|
|
182
|
+
border-radius: 20px;
|
|
183
|
+
transition: background .2s;
|
|
184
|
+
}
|
|
185
|
+
.agy-rtl-slider::before {
|
|
186
|
+
content: '';
|
|
187
|
+
position: absolute;
|
|
188
|
+
width: 14px;
|
|
189
|
+
height: 14px;
|
|
190
|
+
left: 3px;
|
|
191
|
+
bottom: 3px;
|
|
192
|
+
background: #fff;
|
|
193
|
+
border-radius: 50%;
|
|
194
|
+
transition: transform .2s;
|
|
195
|
+
box-shadow: 0 1px 2px rgba(0,0,0,.3);
|
|
196
|
+
}
|
|
197
|
+
.agy-rtl-switch input:checked + .agy-rtl-slider {
|
|
198
|
+
background: #4b9cf5;
|
|
199
|
+
}
|
|
200
|
+
.agy-rtl-switch input:checked + .agy-rtl-slider::before {
|
|
201
|
+
transform: translateX(16px);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* Footer */
|
|
205
|
+
.agy-rtl-panel-footer {
|
|
206
|
+
padding: 8px 16px;
|
|
207
|
+
background: rgba(255,255,255,.02);
|
|
208
|
+
border-top: 1px solid #2a2a2a;
|
|
209
|
+
text-align: center;
|
|
210
|
+
}
|
|
211
|
+
.agy-rtl-gh-link {
|
|
212
|
+
display: inline-flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
gap: 5px;
|
|
215
|
+
color: #555;
|
|
216
|
+
text-decoration: none;
|
|
217
|
+
font-size: 11px;
|
|
218
|
+
transition: color .15s;
|
|
219
|
+
}
|
|
220
|
+
.agy-rtl-gh-link:hover { color: #9cdcfe; }
|
|
221
|
+
`;
|
|
94
222
|
|
|
95
223
|
// ─── Helpers ─────────────────────────────────────────────
|
|
96
224
|
|
|
97
225
|
function getStoredState() {
|
|
98
|
-
try {
|
|
99
|
-
|
|
100
|
-
return s === null ? true : s === 'true';
|
|
101
|
-
} catch (e) { return true; }
|
|
226
|
+
try { var s = localStorage.getItem(STORAGE_KEY); return s === null ? true : s === 'true'; }
|
|
227
|
+
catch (e) { return true; }
|
|
102
228
|
}
|
|
103
|
-
|
|
104
229
|
function setStoredState(v) {
|
|
105
|
-
try { localStorage.setItem(STORAGE_KEY, v ? 'true' : 'false'); }
|
|
106
|
-
catch (e) { /* ignore */ }
|
|
230
|
+
try { localStorage.setItem(STORAGE_KEY, v ? 'true' : 'false'); } catch (e) {}
|
|
107
231
|
}
|
|
108
|
-
|
|
109
232
|
function isRTL(text) {
|
|
110
233
|
if (!text || text.trim().length === 0) return false;
|
|
111
234
|
if (!RTL_REGEX.test(text)) return false;
|
|
@@ -114,32 +237,37 @@ function _agyRtlRendererMain() {
|
|
|
114
237
|
var alpha = text.replace(/[\s\d\W]/g, '').length;
|
|
115
238
|
return alpha > 0 && (m.length / alpha) >= MIN_RTL_RATIO;
|
|
116
239
|
}
|
|
117
|
-
|
|
118
240
|
function applyRTL(el) {
|
|
119
241
|
if (el.getAttribute(PROCESSED_ATTR)) return;
|
|
120
|
-
|
|
242
|
+
// Skip the RTL panel/icon itself
|
|
243
|
+
if (el.closest && (el.closest('#' + PANEL_ID) || el.closest('#' + STATUS_ICON_ID))) return;
|
|
244
|
+
var text = el.textContent || '';
|
|
245
|
+
if (text.trim().length > 0 && isRTL(text)) {
|
|
121
246
|
el.setAttribute(PROCESSED_ATTR, 'true');
|
|
122
|
-
el.style.direction = 'rtl';
|
|
123
|
-
el.style.textAlign = 'start';
|
|
124
|
-
el.style.unicodeBidi = 'plaintext';
|
|
125
247
|
}
|
|
126
248
|
}
|
|
127
|
-
|
|
128
249
|
function removeRTL(el) {
|
|
129
250
|
if (el.getAttribute(PROCESSED_ATTR)) {
|
|
130
251
|
el.removeAttribute(PROCESSED_ATTR);
|
|
131
|
-
el.style.direction = '';
|
|
132
|
-
el.style.textAlign = '';
|
|
133
|
-
el.style.unicodeBidi = '';
|
|
134
252
|
}
|
|
135
253
|
}
|
|
136
254
|
|
|
255
|
+
// Wide selectors — catch all text-bearing elements
|
|
256
|
+
var SELECTORS = [
|
|
257
|
+
'p', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
|
258
|
+
'blockquote', 'td', 'th', 'span', 'a', 'label',
|
|
259
|
+
'div', 'button',
|
|
260
|
+
].join(',');
|
|
261
|
+
|
|
137
262
|
function scanElement(root) {
|
|
138
263
|
if (!root || root.nodeType !== 1) return;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
264
|
+
// Skip our own UI
|
|
265
|
+
if (root.id === PANEL_ID || root.id === STATUS_ICON_ID) return;
|
|
266
|
+
if (root.closest && (root.closest('#' + PANEL_ID) || root.closest('#' + STATUS_ICON_ID))) return;
|
|
142
267
|
|
|
268
|
+
try { if (root.matches && root.matches(SELECTORS)) applyRTL(root); } catch (e) {}
|
|
269
|
+
try { root.querySelectorAll(SELECTORS).forEach(applyRTL); } catch (e) {}
|
|
270
|
+
}
|
|
143
271
|
function clearAllRTL() {
|
|
144
272
|
try { document.querySelectorAll('[' + PROCESSED_ATTR + ']').forEach(removeRTL); } catch (e) {}
|
|
145
273
|
}
|
|
@@ -168,10 +296,10 @@ function _agyRtlRendererMain() {
|
|
|
168
296
|
|
|
169
297
|
function injectCSS() {
|
|
170
298
|
if (document.getElementById('agy-rtl-styles')) return;
|
|
171
|
-
var
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
(document.head || document.documentElement).appendChild(
|
|
299
|
+
var s = document.createElement('style');
|
|
300
|
+
s.id = 'agy-rtl-styles';
|
|
301
|
+
s.textContent = CSS;
|
|
302
|
+
(document.head || document.documentElement).appendChild(s);
|
|
175
303
|
}
|
|
176
304
|
|
|
177
305
|
function createStatusIcon() {
|
|
@@ -179,38 +307,55 @@ function _agyRtlRendererMain() {
|
|
|
179
307
|
|
|
180
308
|
var icon = document.createElement('div');
|
|
181
309
|
icon.id = STATUS_ICON_ID;
|
|
182
|
-
icon.className = 'agy-rtl-status-icon';
|
|
310
|
+
icon.className = 'agy-rtl-status-icon' + (isEnabled ? ' active' : '');
|
|
183
311
|
icon.setAttribute('title', 'Antigravity Smart RTL');
|
|
184
312
|
|
|
313
|
+
// Globe SVG
|
|
185
314
|
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
186
|
-
svg.setAttribute('width', '
|
|
187
|
-
svg.setAttribute('height', '
|
|
315
|
+
svg.setAttribute('width', '15');
|
|
316
|
+
svg.setAttribute('height', '15');
|
|
188
317
|
svg.setAttribute('viewBox', '0 0 24 24');
|
|
189
318
|
svg.setAttribute('fill', 'none');
|
|
190
319
|
svg.setAttribute('stroke', 'currentColor');
|
|
191
|
-
svg.setAttribute('stroke-width', '
|
|
320
|
+
svg.setAttribute('stroke-width', '1.8');
|
|
192
321
|
svg.setAttribute('stroke-linecap', 'round');
|
|
193
322
|
svg.setAttribute('stroke-linejoin', 'round');
|
|
194
323
|
|
|
195
|
-
var
|
|
196
|
-
|
|
197
|
-
svg.appendChild(
|
|
198
|
-
var
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
svg.appendChild(
|
|
202
|
-
var
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
svg.appendChild(l2);
|
|
206
|
-
|
|
324
|
+
var circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
|
|
325
|
+
circle.setAttribute('cx', '12'); circle.setAttribute('cy', '12'); circle.setAttribute('r', '10');
|
|
326
|
+
svg.appendChild(circle);
|
|
327
|
+
var line1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
|
328
|
+
line1.setAttribute('x1', '2'); line1.setAttribute('y1', '12');
|
|
329
|
+
line1.setAttribute('x2', '22'); line1.setAttribute('y2', '12');
|
|
330
|
+
svg.appendChild(line1);
|
|
331
|
+
var ell = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
332
|
+
ell.setAttribute('d', 'M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z');
|
|
333
|
+
svg.appendChild(ell);
|
|
207
334
|
icon.appendChild(svg);
|
|
208
335
|
|
|
209
|
-
var
|
|
210
|
-
|
|
211
|
-
|
|
336
|
+
var lbl = document.createElement('span');
|
|
337
|
+
lbl.textContent = 'RTL';
|
|
338
|
+
lbl.style.cssText = 'direction:ltr!important;';
|
|
339
|
+
icon.appendChild(lbl);
|
|
340
|
+
|
|
341
|
+
// Hover to open panel
|
|
342
|
+
icon.addEventListener('mouseenter', function () {
|
|
343
|
+
clearTimeout(hoverTimeout);
|
|
344
|
+
hoverTimeout = setTimeout(function () { showPanel(); }, 200);
|
|
345
|
+
});
|
|
346
|
+
icon.addEventListener('mouseleave', function () {
|
|
347
|
+
clearTimeout(hoverTimeout);
|
|
348
|
+
hoverTimeout = setTimeout(function () {
|
|
349
|
+
var panel = document.getElementById(PANEL_ID);
|
|
350
|
+
if (panel && !panel.matches(':hover')) hidePanel();
|
|
351
|
+
}, 300);
|
|
352
|
+
});
|
|
353
|
+
// Also toggle on click
|
|
354
|
+
icon.addEventListener('click', function (e) {
|
|
355
|
+
e.stopPropagation();
|
|
356
|
+
if (panelVisible) hidePanel(); else showPanel();
|
|
357
|
+
});
|
|
212
358
|
|
|
213
|
-
icon.addEventListener('click', function (e) { e.stopPropagation(); togglePanel(); });
|
|
214
359
|
document.body.appendChild(icon);
|
|
215
360
|
}
|
|
216
361
|
|
|
@@ -221,6 +366,12 @@ function _agyRtlRendererMain() {
|
|
|
221
366
|
panel.id = PANEL_ID;
|
|
222
367
|
panel.className = 'agy-rtl-panel';
|
|
223
368
|
|
|
369
|
+
// Keep panel open on hover
|
|
370
|
+
panel.addEventListener('mouseenter', function () { clearTimeout(hoverTimeout); });
|
|
371
|
+
panel.addEventListener('mouseleave', function () {
|
|
372
|
+
hoverTimeout = setTimeout(function () { hidePanel(); }, 300);
|
|
373
|
+
});
|
|
374
|
+
|
|
224
375
|
// Header
|
|
225
376
|
var header = document.createElement('div');
|
|
226
377
|
header.className = 'agy-rtl-panel-header';
|
|
@@ -230,7 +381,10 @@ function _agyRtlRendererMain() {
|
|
|
230
381
|
header.appendChild(title);
|
|
231
382
|
panel.appendChild(header);
|
|
232
383
|
|
|
233
|
-
//
|
|
384
|
+
// Body
|
|
385
|
+
var body = document.createElement('div');
|
|
386
|
+
body.className = 'agy-rtl-panel-body';
|
|
387
|
+
|
|
234
388
|
var row = document.createElement('div');
|
|
235
389
|
row.className = 'agy-rtl-panel-row';
|
|
236
390
|
var label = document.createElement('span');
|
|
@@ -249,16 +403,12 @@ function _agyRtlRendererMain() {
|
|
|
249
403
|
sw.appendChild(cb);
|
|
250
404
|
sw.appendChild(slider);
|
|
251
405
|
row.appendChild(sw);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
// Separator
|
|
255
|
-
var sep = document.createElement('div');
|
|
256
|
-
sep.className = 'agy-rtl-panel-sep';
|
|
257
|
-
panel.appendChild(sep);
|
|
406
|
+
body.appendChild(row);
|
|
407
|
+
panel.appendChild(body);
|
|
258
408
|
|
|
259
|
-
//
|
|
260
|
-
var
|
|
261
|
-
|
|
409
|
+
// Footer
|
|
410
|
+
var footer = document.createElement('div');
|
|
411
|
+
footer.className = 'agy-rtl-panel-footer';
|
|
262
412
|
var ghLink = document.createElement('a');
|
|
263
413
|
ghLink.className = 'agy-rtl-gh-link';
|
|
264
414
|
ghLink.href = GITHUB_URL;
|
|
@@ -266,28 +416,31 @@ function _agyRtlRendererMain() {
|
|
|
266
416
|
ghLink.rel = 'noopener noreferrer';
|
|
267
417
|
|
|
268
418
|
var ghSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
269
|
-
ghSvg.setAttribute('width', '
|
|
270
|
-
ghSvg.setAttribute('
|
|
271
|
-
ghSvg.setAttribute('viewBox', '0 0 16 16');
|
|
272
|
-
ghSvg.setAttribute('fill', 'currentColor');
|
|
419
|
+
ghSvg.setAttribute('width', '12'); ghSvg.setAttribute('height', '12');
|
|
420
|
+
ghSvg.setAttribute('viewBox', '0 0 16 16'); ghSvg.setAttribute('fill', 'currentColor');
|
|
273
421
|
var ghP = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
274
422
|
ghP.setAttribute('d', 'M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z');
|
|
275
423
|
ghSvg.appendChild(ghP);
|
|
276
424
|
ghLink.appendChild(ghSvg);
|
|
277
|
-
|
|
278
425
|
var ghText = document.createElement('span');
|
|
279
|
-
ghText.textContent = '
|
|
426
|
+
ghText.textContent = 'Star on GitHub';
|
|
280
427
|
ghLink.appendChild(ghText);
|
|
281
|
-
|
|
282
|
-
panel.appendChild(
|
|
428
|
+
footer.appendChild(ghLink);
|
|
429
|
+
panel.appendChild(footer);
|
|
283
430
|
|
|
284
|
-
//
|
|
431
|
+
// Toggle event
|
|
285
432
|
cb.addEventListener('change', function () {
|
|
286
433
|
isEnabled = cb.checked;
|
|
287
434
|
setStoredState(isEnabled);
|
|
288
435
|
updateState();
|
|
289
436
|
});
|
|
290
437
|
|
|
438
|
+
// Close on Escape
|
|
439
|
+
document.addEventListener('keydown', function (e) {
|
|
440
|
+
if (e.key === 'Escape' && panelVisible) hidePanel();
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// Close on outside click
|
|
291
444
|
document.addEventListener('click', function (e) {
|
|
292
445
|
var p = document.getElementById(PANEL_ID);
|
|
293
446
|
var ic = document.getElementById(STATUS_ICON_ID);
|
|
@@ -297,14 +450,9 @@ function _agyRtlRendererMain() {
|
|
|
297
450
|
document.body.appendChild(panel);
|
|
298
451
|
}
|
|
299
452
|
|
|
300
|
-
function togglePanel() {
|
|
301
|
-
panelVisible ? hidePanel() : showPanel();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
453
|
function showPanel() {
|
|
305
454
|
var panel = document.getElementById(PANEL_ID);
|
|
306
455
|
if (!panel) { createPanel(); panel = document.getElementById(PANEL_ID); }
|
|
307
|
-
|
|
308
456
|
var icon = document.getElementById(STATUS_ICON_ID);
|
|
309
457
|
if (icon) {
|
|
310
458
|
var r = icon.getBoundingClientRect();
|
|
@@ -322,10 +470,10 @@ function _agyRtlRendererMain() {
|
|
|
322
470
|
}
|
|
323
471
|
|
|
324
472
|
function updateState() {
|
|
325
|
-
var
|
|
326
|
-
if (
|
|
327
|
-
if (isEnabled)
|
|
328
|
-
else
|
|
473
|
+
var icon = document.getElementById(STATUS_ICON_ID);
|
|
474
|
+
if (icon) {
|
|
475
|
+
if (isEnabled) icon.classList.add('active');
|
|
476
|
+
else icon.classList.remove('active');
|
|
329
477
|
}
|
|
330
478
|
var cb = document.getElementById(TOGGLE_BTN_ID);
|
|
331
479
|
if (cb) cb.checked = isEnabled;
|