Repository navigation
Expand file tree
/
Copy pathoptions.js
More file actions
322 lines (264 loc) · 9.33 KB
/
Copy pathoptions.js
File metadata and controls
322 lines (264 loc) · 9.33 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
// ==================== 浏览器兼容层 ====================
const browserAPI = globalThis.browser || globalThis.chrome;
// 默认的常见地址列表(与 background.js 保持一致)
const DEFAULT_BYPASS_PATTERNS = [
'localhost'
];
// DOM 元素
const patternInput = document.getElementById('patternInput');
const addBtn = document.getElementById('addBtn');
const customPatternsList = document.getElementById('customPatternsList');
const defaultPatternsList = document.getElementById('defaultPatternsList');
const messageDiv = document.getElementById('message');
const messageText = messageDiv.querySelector('.message-text');
let messageTimer = null;
const defaultPlatformSelect = document.getElementById('defaultPlatform');
// 功能开关 DOM 元素
const featureOmnibox = document.getElementById('featureOmnibox');
const featureSearchRedirect = document.getElementById('featureSearchRedirect');
const featureDnsIntercept = document.getElementById('featureDnsIntercept');
const searchRedirectOptions = document.getElementById('searchRedirectOptions');
const searchModeAutoJump = document.getElementById('searchModeAutoJump');
const searchModeTabJump = document.getElementById('searchModeTabJump');
const searchModeNewTab = document.getElementById('searchModeNewTab');
// 高级设置元素
const advancedToggle = document.getElementById('advancedToggle');
const advancedContent = document.getElementById('advancedContent');
// 可选的默认平台列表(需与 background.js 中的代码托管平台保持一致)
const AVAILABLE_DEFAULT_PLATFORMS = ['github', 'gitlab', 'bitbucket', 'gitee'];
// 加载默认平台配置
async function loadDefaultPlatform() {
const result = await browserAPI.storage.sync.get({
defaultPlatform: 'github'
});
const value = result.defaultPlatform;
defaultPlatformSelect.value = AVAILABLE_DEFAULT_PLATFORMS.includes(value) ? value : 'github';
}
// 国际化处理
function localizeHtml() {
// 翻译带有 data-i18n 属性的元素
document.querySelectorAll('[data-i18n]').forEach(el => {
const message = browserAPI.i18n.getMessage(el.getAttribute('data-i18n'));
if (message) {
el.textContent = message;
}
});
// 翻译带有 data-i18n-placeholder 属性的元素
document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
const message = browserAPI.i18n.getMessage(el.getAttribute('data-i18n-placeholder'));
if (message) {
el.placeholder = message;
}
});
}
// 保存默认平台配置
async function saveDefaultPlatform() {
const value = defaultPlatformSelect.value;
await browserAPI.storage.sync.set({ defaultPlatform: value });
showMessage(browserAPI.i18n.getMessage('saved_success'), 'success');
}
// 显示消息
function showMessage(text, type = 'success') {
if (messageTimer) {
clearTimeout(messageTimer);
messageTimer = null;
}
messageText.textContent = text;
messageDiv.className = `message ${type}`;
requestAnimationFrame(() => {
messageDiv.classList.add('is-visible');
});
messageTimer = setTimeout(() => {
messageDiv.classList.add('is-leaving');
messageDiv.classList.remove('is-visible');
messageTimer = setTimeout(() => {
messageDiv.className = 'message';
messageDiv.classList.remove('is-leaving');
messageTimer = null;
}, 320);
}, 3000);
}
// 加载并显示自定义白名单
async function loadCustomPatterns() {
const result = await browserAPI.storage.sync.get({
customBypassPatterns: []
});
const patterns = result.customBypassPatterns;
if (patterns.length === 0) {
const emptyDiv = document.createElement('div');
emptyDiv.className = 'empty-state';
emptyDiv.textContent = browserAPI.i18n.getMessage('no_custom_rules');
customPatternsList.innerHTML = '';
customPatternsList.appendChild(emptyDiv);
} else {
customPatternsList.innerHTML = '';
patterns.forEach((pattern, index) => {
const li = document.createElement('li');
li.className = 'pattern-item';
const span = document.createElement('span');
span.className = 'pattern-text';
span.textContent = pattern;
const btn = document.createElement('button');
btn.className = 'delete-btn';
btn.dataset.index = index;
btn.textContent = browserAPI.i18n.getMessage('delete');
btn.addEventListener('click', async (e) => {
const idx = parseInt(e.target.dataset.index);
await deletePattern(idx);
});
li.appendChild(span);
li.appendChild(btn);
customPatternsList.appendChild(li);
});
}
}
// 显示默认白名单
function loadDefaultPatterns() {
defaultPatternsList.innerHTML = '';
DEFAULT_BYPASS_PATTERNS.forEach(pattern => {
const li = document.createElement('li');
li.textContent = pattern;
defaultPatternsList.appendChild(li);
});
}
// 添加新的白名单规则
async function addPattern() {
const pattern = patternInput.value.trim();
if (!pattern) {
showMessage(browserAPI.i18n.getMessage('enter_pattern_error'), 'error');
return;
}
// 获取当前的自定义白名单
const result = await browserAPI.storage.sync.get({
customBypassPatterns: []
});
const patterns = result.customBypassPatterns;
// 检查是否已存在
if (patterns.includes(pattern)) {
showMessage('该规则已存在', 'error');
return;
}
// 添加新规则
patterns.push(pattern);
// 保存到存储
await browserAPI.storage.sync.set({
customBypassPatterns: patterns
});
// 清空输入框
patternInput.value = '';
// 重新加载列表
await loadCustomPatterns();
showMessage('规则添加成功!', 'success');
}
// 删除白名单规则
async function deletePattern(index) {
const result = await browserAPI.storage.sync.get({
customBypassPatterns: []
});
const patterns = result.customBypassPatterns;
patterns.splice(index, 1);
await browserAPI.storage.sync.set({
customBypassPatterns: patterns
});
await loadCustomPatterns();
showMessage('规则已删除', 'success');
}
// HTML 转义
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 事件监听
addBtn.addEventListener('click', addPattern);
patternInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
addPattern();
}
});
// 监听默认平台变化
defaultPlatformSelect.addEventListener('change', saveDefaultPlatform);
// ==================== 功能开关管理 ====================
// 加载功能开关配置
async function loadFeatureToggles() {
const result = await browserAPI.storage.sync.get({
featureOmnibox: true,
featureSearchRedirect: true,
featureDnsIntercept: true,
searchRedirectMode: 'autoJump'
});
featureOmnibox.checked = result.featureOmnibox;
featureSearchRedirect.checked = result.featureSearchRedirect;
featureDnsIntercept.checked = result.featureDnsIntercept;
if (result.searchRedirectMode === 'autoJump') {
searchModeAutoJump.checked = true;
} else if (result.searchRedirectMode === 'tabJump') {
searchModeTabJump.checked = true;
} else {
searchModeNewTab.checked = true;
}
updateSearchRedirectOptionsUI();
}
// 保存功能开关配置
async function saveFeatureToggles() {
await browserAPI.storage.sync.set({
featureOmnibox: featureOmnibox.checked,
featureSearchRedirect: featureSearchRedirect.checked,
featureDnsIntercept: featureDnsIntercept.checked
});
showMessage(browserAPI.i18n.getMessage('saved_success'), 'success');
}
// 保存搜索跳转模式
async function saveSearchRedirectMode() {
let mode = 'autoJump';
if (searchModeAutoJump.checked) {
mode = 'autoJump';
} else if (searchModeTabJump.checked) {
mode = 'tabJump';
} else if (searchModeNewTab.checked) {
mode = 'newTab';
}
await browserAPI.storage.sync.set({
searchRedirectMode: mode
});
showMessage(browserAPI.i18n.getMessage('saved_success'), 'success');
}
// 更新搜索跳转选项 UI 状态
function updateSearchRedirectOptionsUI() {
if (featureSearchRedirect.checked) {
searchRedirectOptions.classList.remove('sub-option-disabled');
} else {
searchRedirectOptions.classList.add('sub-option-disabled');
}
}
// 监听功能开关变化
featureOmnibox.addEventListener('change', saveFeatureToggles);
featureDnsIntercept.addEventListener('change', saveFeatureToggles);
featureSearchRedirect.addEventListener('change', () => {
saveFeatureToggles();
updateSearchRedirectOptionsUI();
});
// 监听搜索跳转模式变化
searchModeAutoJump.addEventListener('change', saveSearchRedirectMode);
searchModeTabJump.addEventListener('change', saveSearchRedirectMode);
searchModeNewTab.addEventListener('change', saveSearchRedirectMode);
// ==================== 高级设置折叠 ====================
// 监听高级设置折叠按钮
advancedToggle.addEventListener('click', () => {
const isCollapsed = advancedContent.classList.contains('collapsed');
if (isCollapsed) {
advancedContent.classList.remove('collapsed');
advancedToggle.querySelector('.advanced-toggle').classList.remove('collapsed');
} else {
advancedContent.classList.add('collapsed');
advancedToggle.querySelector('.advanced-toggle').classList.add('collapsed');
}
});
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', () => {
localizeHtml();
loadDefaultPatterns();
loadCustomPatterns();
loadDefaultPlatform();
loadFeatureToggles();
});