Compare commits

..
19 Commits
Author SHA1 Message Date
go0p 62cb22d2ab Enhance webpack build script with production mode and progress tracking 2025-03-02 15:31:21 +08:00
go0p 2c88e8764a update build script to use webpack directly 2025-03-02 15:31:20 +08:00
go0p 70c33af717 fix chrome doesn't give a damn about proxy on localhost 2025-03-02 15:31:20 +08:00
go0p 74c5d4ae2b fix setting pac 2025-03-02 15:31:20 +08:00
go0p 462648a71f todo switch 2025-03-02 15:31:20 +08:00
go0p 6b45661fe3 fix popup options.html context 2025-03-02 15:31:20 +08:00
go0p fd275d5e7d add inject content ui 2025-03-02 15:31:20 +08:00
go0p b08a806ce7 yakit mitm config 2025-03-02 15:31:20 +08:00
go0p 5104c5b620 ui v0.0.2-beta 2025-03-02 15:31:20 +08:00
go0p f3d41a3c6c ui v0.0.1-beta 2025-03-02 15:31:20 +08:00
go0p 598314a111 ui v0.0.1-beta 2025-03-02 15:31:20 +08:00
go0p bb822b2d5b fix ui 2025-03-02 15:31:20 +08:00
go0p 3e99ba57ac fix 2025-03-02 15:31:20 +08:00
go0p 8e2af7a869 use indexedDB manager proxySwitch 2025-03-02 15:31:20 +08:00
go0p 47ccb37a26 add proxy switch demo 2025-03-02 15:31:20 +08:00
go0p 5cb1d1fa22 add proxy switch demo 2025-03-02 15:31:20 +08:00
go0p 391f7292e7 fix inject 2025-03-02 15:31:20 +08:00
go0p 5dc3c4c248 feat(wsc) brute encrypt demo 2025-03-02 15:31:20 +08:00
go0p 19c5b6e2ba feat(wsc) fuzzer demo 2025-03-02 15:31:20 +08:00
6 changed files with 176 additions and 414 deletions
+8 -32
View File
@@ -3,8 +3,9 @@ name: Build and Release
on: workflow_dispatch on: workflow_dispatch
jobs: jobs:
build-and-publish: build-and-release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -21,18 +22,17 @@ jobs:
- name: Build project - name: Build project
run: yarn build run: yarn build
- name: Get version
id: version
run: |
VERSION=$(jq -r '.version' build/manifest.json)
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "build_time=$(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_OUTPUT
- name: Zip build artifacts - name: Zip build artifacts
run: | run: |
cd build cd build
zip -r ../extension.zip . zip -r ../extension.zip .
- name: Generate version number
id: version
run: |
echo "version=1.0.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "build_time=$(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_OUTPUT
- name: Create Release - name: Create Release
id: create_release id: create_release
uses: actions/create-release@v1 uses: actions/create-release@v1
@@ -57,27 +57,3 @@ jobs:
asset_path: ./extension.zip asset_path: ./extension.zip
asset_name: yakit-chrome-extension-v${{ steps.version.outputs.version }}.zip asset_name: yakit-chrome-extension-v${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip asset_content_type: application/zip
- name: Upload Extension To OSS
uses: tvrcgo/upload-to-oss@master
with:
key-id: ${{ secrets.OSS_KEY_ID }}
key-secret: ${{ secrets.OSS_KEY_SECRET }}
region: oss-accelerate
bucket: yaklang
assets: |
extension.zip:/chrome-extension/yakit-chrome-extension-v${{ steps.version.outputs.version }}.zip
- name: Update OSS latest version file
run: echo ${{ steps.version.outputs.version }} > ./extension-version.txt
- name: Upload Version File to OSS
uses: tvrcgo/upload-to-oss@master
with:
key-id: ${{ secrets.OSS_KEY_ID }}
key-secret: ${{ secrets.OSS_KEY_SECRET }}
region: oss-accelerate
bucket: yaklang
assets: |
./extension-version.txt:/chrome-extension/latest-version.txt
+2 -2
View File
@@ -1,7 +1,7 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "Yakit Chrome Endpoint", "name": "Yakit Chrome Endpoint",
"version": "0.0.4", "version": "1.0",
"description": "A Endpoint for Yakit MITM or more", "description": "A Endpoint for Yakit MITM or more",
"options_ui": { "options_ui": {
"page": "proxy/options.html", "page": "proxy/options.html",
@@ -24,7 +24,7 @@
}, },
"content_scripts": [ "content_scripts": [
{ {
"matches": ["<all_urls>","http://mitm/"], "matches": ["http://mitm/"],
"run_at": "document_start", "run_at": "document_start",
"js": ["proxy/content.js"] "js": ["proxy/content.js"]
} }
+6 -13
View File
@@ -290,16 +290,6 @@ async function checkAndSetInitialProxy() {
// 确保默认配置存在 // 确保默认配置存在
await ProxySettings.setDefaultConfigs(); await ProxySettings.setDefaultConfigs();
// 获取上次保存的代理配置
const lastProxy = await proxyStore.getCurrentProxy();
if (lastProxy) {
// 如果有上次的配置,恢复它
console.log('Restoring last proxy configuration:', lastProxy);
await handleSetProxyConfig(lastProxy, () => {});
return;
}
// 获取当前的代理设置 // 获取当前的代理设置
const settings = await getProxySettings(); const settings = await getProxySettings();
console.log('Current proxy settings:', settings); console.log('Current proxy settings:', settings);
@@ -348,7 +338,7 @@ async function checkAndSetInitialProxy() {
} }
} }
// 如果没有之前的配置也没有检测到代理,才设置为系统代理 // 如果没有检测到代理或已存在配置,则设置为系统代理
await handleSetProxyConfig({ await handleSetProxyConfig({
id: 'system', id: 'system',
name: '[系统代理]', name: '[系统代理]',
@@ -356,6 +346,9 @@ async function checkAndSetInitialProxy() {
enabled: true enabled: true
}, () => {}); }, () => {});
// 设置认证监听
await ProxyAuth.setupAuthListener();
} catch (error) { } catch (error) {
console.error('Error during initialization:', error); console.error('Error during initialization:', error);
} }
@@ -363,10 +356,10 @@ async function checkAndSetInitialProxy() {
// 修改 setupProxyHandlers 函数 // 修改 setupProxyHandlers 函数
export function setupProxyHandlers() { export function setupProxyHandlers() {
// 设置代理错误处理 // 设置代理错误处理和认证
ProxyAuth.setupErrorHandler(); ProxyAuth.setupErrorHandler();
// 设置认证监听
ProxyAuth.setupAuthListener(); ProxyAuth.setupAuthListener();
// 设置代理请求监听器 // 设置代理请求监听器
setupProxyRequestListener(); setupProxyRequestListener();
+154 -357
View File
@@ -105,7 +105,6 @@ async function switchProxy(config) {
}; };
} }
// 发送配置更改消息
await sendMessageWithRetry({ await sendMessageWithRetry({
action: ProxyActionType.SET_PROXY_CONFIG, action: ProxyActionType.SET_PROXY_CONFIG,
config: proxyConfig config: proxyConfig
@@ -148,9 +147,6 @@ const PanelManager = {
_lastUpdate: null, // 添加最后更新时间戳 _lastUpdate: null, // 添加最后更新时间戳
_lastState: null, _lastState: null,
_pollingInterval: null, _pollingInterval: null,
isDragging: false,
startY: 0,
currentY: 0,
init() { init() {
// 确保 document.body 存在 // 确保 document.body 存在
@@ -210,249 +206,197 @@ const PanelManager = {
style.textContent = ` style.textContent = `
.floating-panel { .floating-panel {
position: fixed; position: fixed;
top: 30%; top: 20px;
right: 0; right: 0;
transform: translateY(-30%); width: 180px;
background: white; background: white;
border-radius: 8px 0 0 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 2147483647; z-index: 2147483647;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
width: 50px; transition: transform 0.3s ease;
height: 40px;
overflow: hidden;
transition: width 0.2s cubic-bezier(0.4, 0, 0.2, 1),
height 0.2s cubic-bezier(0.4, 0, 0.2, 1),
background-color 0.2s ease;
} }
/* 吸附状态 */ .floating-panel.collapsed {
.floating-panel:not(.expanded):not(.dragging) { transform: translateX(100%);
border-radius: 50px 0 0 50px;
box-shadow: -4px 0 20px rgba(0,0,0,0.15);
border: 1px solid #eee;
border-right: none;
}
/* 拖动状态 */
.floating-panel.dragging {
cursor: grabbing !important;
user-select: none;
opacity: 0.95;
transition: none;
}
.floating-panel.dragging * {
cursor: grabbing !important;
}
.floating-panel:active {
cursor: grabbing;
}
.floating-panel .panel-header {
cursor: grab;
}
.floating-panel .panel-header:active {
cursor: grabbing;
}
/* 吸附状态悬浮时 */
.floating-panel:not(.expanded):hover {
width: 120px;
background: #fff7e6;
border-color: #ffd591;
}
/* 展开状态 - 立即应用圆角变化 */
.floating-panel.expanded {
width: 180px;
height: auto;
max-height: 400px;
border-radius: 8px 0 0 8px;
box-shadow: -2px 0 10px rgba(0,0,0,0.1);
border: 1px solid #eee;
border-right: none;
/* 展开时立即应用新的圆角 */
transition:
width 0.2s cubic-bezier(0.4, 0, 0.2, 1),
height 0.2s cubic-bezier(0.4, 0, 0.2, 1),
border-radius 0s,
background-color 0.2s ease;
} }
.panel-header { .panel-header {
height: 40px; padding: 4px;
min-height: 40px;
display: flex;
align-items: center;
padding: 0 8px;
cursor: pointer;
user-select: none;
}
/* 吸附状态的头部 */
.floating-panel:not(.expanded) .panel-header {
background: transparent;
}
/* 展开状态的头部 */
.floating-panel.expanded .panel-header {
background: #f8f9fa;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
border-radius: 8px 0 0 0;
background: #f8f9fa;
display: flex;
justify-content: space-between;
align-items: center;
} }
.header-content { .collapse-trigger {
position: absolute;
left: -20px;
top: 0;
width: 20px;
height: 100%;
background: #f8f9fa;
border-radius: 8px 0 0 8px;
cursor: pointer;
display: flex; display: flex;
align-items: center; align-items: center;
flex: 1; justify-content: center;
overflow: hidden; box-shadow: -2px 0 5px rgba(0,0,0,0.1);
} }
/* 优化图标大小过渡 */ .collapse-trigger:hover {
.yak-icon { background: #e9ecef;
width: 36px;
height: 36px;
min-width: 36px;
object-fit: contain;
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
} }
.floating-panel.expanded .yak-icon { .collapse-trigger::after {
width: 24px; content: '◀';
height: 24px; transition: transform 0.3s ease;
min-width: 24px;
} }
.active-proxy-info { .floating-panel.collapsed .collapse-trigger::after {
display: flex; transform: rotate(180deg);
align-items: center;
margin-left: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #ff6b00;
font-size: 13px;
font-weight: 500;
}
.active-proxy-info span:first-child {
margin-right: 6px;
filter: drop-shadow(0 1px 2px rgba(0,0,0,0.1));
} }
.panel-content { .panel-content {
display: none; padding: 4px;
background: white;
overflow-y: auto;
max-height: 360px;
opacity: 0;
transition: opacity 0.2s ease;
}
.floating-panel.expanded .panel-content {
display: block;
opacity: 1;
}
.panel-content::-webkit-scrollbar {
width: 4px;
}
.panel-content::-webkit-scrollbar-track {
background: #f5f5f5;
}
.panel-content::-webkit-scrollbar-thumb {
background: #ddd;
border-radius: 4px;
}
.panel-content::-webkit-scrollbar-thumb:hover {
background: #ccc;
} }
.proxy-item { .proxy-item {
position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 8px 12px; padding: 4px 10px;
cursor: pointer; cursor: pointer;
transition: all 0.2s; transition: all 0.2s;
white-space: nowrap; color: #666;
position: relative; border-left: 3px solid transparent;
overflow: hidden;
} }
.proxy-item:hover { .proxy-item > span {
background: #fff7e6; position: relative;
z-index: 1;
}
.watermark-icon {
position: absolute;
right: 0;
width: 100%;
height: 100%;
opacity: 0.3;
pointer-events: none;
display: none;
object-fit: contain;
object-position: right center;
padding: 4px;
}
.proxy-item.active .watermark-icon {
display: block;
} }
.proxy-item.active { .proxy-item.active {
color: #ff6b00 !important;
background: #fff7e6; background: #fff7e6;
color: #ff6b00; border-left: 3px solid #ff6b00;
}
.proxy-item.active span:first-child {
color: #ff6b00 !important;
} }
.proxy-item span:first-child { .proxy-item span:first-child {
margin-right: 8px; margin-right: 8px;
font-size: 16px; font-size: 16px;
filter: drop-shadow(0 1px 2px rgba(0,0,0,0.1)); color: #666;
transition: color 0.2s;
} }
.proxy-status { .proxy-item:hover {
position: absolute; background: #f5f5f5;
right: 12px;
width: 6px;
height: 6px;
border-radius: 50%;
background: #52c41a;
box-shadow: 0 0 4px rgba(82,196,26,0.3);
} }
.proxy-item.active .proxy-status { .proxy-item:hover span:first-child {
background: #ff6b00; color: #ff6b00;
box-shadow: 0 0 4px rgba(255,107,0,0.3); }
.add-proxy {
display: flex;
align-items: center;
padding: 4px 10px;
color: #1890ff;
cursor: pointer;
border-top: 1px solid #eee;
transition: all 0.2s;
}
.add-proxy:hover {
background: #f5f5f5;
}
.settings {
padding: 4px 10px;
color: #666;
cursor: pointer;
border-top: 1px solid #eee;
transition: all 0.2s;
}
.settings:hover {
background: #f5f5f5;
}
.panel-header .header-content {
display: flex;
align-items: center;
gap: 8px;
padding: 0 4px;
}
.yak-icon {
width: 24px;
height: 24px;
object-fit: contain;
} }
.divider { .divider {
height: 1px; height: 1px;
background: #f0f0f0; background-color: #eee;
margin: 4px 0; margin: 4px 0;
} }
.action-button {
display: flex;
align-items: center;
padding: 8px 12px;
cursor: pointer;
transition: all 0.2s;
white-space: nowrap;
color: #666;
}
.action-button:hover {
background: #fff7e6;
color: #ff6b00;
}
.action-button span:first-child {
margin-right: 8px;
filter: drop-shadow(0 1px 2px rgba(0,0,0,0.1));
}
`; `;
// 创建面板内容 // 创建面板内容
const panel = document.createElement('div'); const panel = document.createElement('div');
panel.className = 'floating-panel'; panel.className = 'floating-panel';
panel.innerHTML = ` panel.innerHTML = `
<div class="collapse-trigger"></div>
<div class="panel-header"> <div class="panel-header">
<div class="header-content"> <div class="header-content">
<img src="${YAK_ICON_URL}" class="yak-icon" alt="Yak" /> <img src="${YAK_ICON_URL}" class="yak-icon" alt="Yak" />
<div class="active-proxy-info"> <span>代理设置</span>
<!-- 当前代理信息将动态更新 -->
</div>
</div> </div>
</div> </div>
<div class="panel-content"> <div class="panel-content">
<!-- 内容将由 _buildPanelHtml 方法动态生成 --> <div class="proxy-item active">
<span>🟢</span>
<span>[直接连接]</span>
</div>
<div class="proxy-item">
<span>⚙️</span>
<span>[系统代理]</span>
</div>
<div class="divider"></div>
<div class="add-proxy">
<span>➕</span>
<span>[添加代理...]</span>
</div>
<div class="settings">
<span>👨‍💻</span>
<span>选项</span>
</div>
</div> </div>
`; `;
@@ -465,20 +409,12 @@ const PanelManager = {
document.body.appendChild(container); document.body.appendChild(container);
this.panel = container; this.panel = container;
// 添加折叠触发器的点击事件
const floatingPanel = shadow.querySelector('.floating-panel'); const floatingPanel = shadow.querySelector('.floating-panel');
const header = shadow.querySelector('.panel-header'); const collapseTrigger = shadow.querySelector('.collapse-trigger');
// 添加拖拽功能 collapseTrigger.addEventListener('click', () => {
this._initDragFeature(header, floatingPanel); floatingPanel.classList.toggle('collapsed');
// 添加自动收起功能
this._initAutoCollapse(floatingPanel);
// 添加点击展开/收起功能
header.addEventListener('click', (e) => {
if (!this.isDragging) {
floatingPanel.classList.toggle('expanded');
}
}); });
// 设置消息监听和开始轮询 // 设置消息监听和开始轮询
@@ -596,29 +532,6 @@ const PanelManager = {
} }
}); });
} }
// 更新当前代理信息显示
const activeProxyInfo = this.panel.shadowRoot?.querySelector('.active-proxy-info');
if (activeProxyInfo) {
let proxyIcon = '🟢';
let proxyName = '直接连接';
if (currentProxy.currentMode === 'system') {
proxyIcon = '⚙️';
proxyName = '系统代理';
} else if (currentProxy.currentMode === 'fixed_servers') {
const activeConfig = configs.find(c => c.enabled);
if (activeConfig) {
proxyIcon = activeConfig.proxyType === 'pac_script' ? '📜' : '🌐';
proxyName = activeConfig.name || '未命名代理';
}
}
activeProxyInfo.innerHTML = `
<span>${proxyIcon}</span>
<span>${proxyName}</span>
`;
}
} catch (error) { } catch (error) {
console.error('Error updating panel:', error); console.error('Error updating panel:', error);
} finally { } finally {
@@ -638,16 +551,16 @@ const PanelManager = {
<div class="proxy-item ${currentProxy.currentMode === 'direct' ? 'active' : ''}" <div class="proxy-item ${currentProxy.currentMode === 'direct' ? 'active' : ''}"
data-id="direct" data-id="direct"
title="直接连接"> title="直接连接">
<span>🟢</span> <span style="color: ${currentProxy.currentMode === 'direct' ? '#ff6b00' : '#666'}">🟢</span>
<span>直接连接</span> <span>[直接连接]</span>
${currentProxy.currentMode === 'direct' ? '<div class="proxy-status"></div>' : ''} <img src="${YAK_ICON_URL}" class="watermark-icon" alt="" />
</div> </div>
<div class="proxy-item ${currentProxy.currentMode === 'system' ? 'active' : ''}" <div class="proxy-item ${currentProxy.currentMode === 'system' ? 'active' : ''}"
data-id="system" data-id="system"
title="系统代理"> title="系统代理">
<span>⚙️</span> <span style="color: ${currentProxy.currentMode === 'system' ? '#ff6b00' : '#666'}">⚙️</span>
<span>系统代理</span> <span>[系统代理]</span>
${currentProxy.currentMode === 'system' ? '<div class="proxy-status"></div>' : ''} <img src="${YAK_ICON_URL}" class="watermark-icon" alt="" />
</div> </div>
<div class="divider"></div> <div class="divider"></div>
`; `;
@@ -655,39 +568,37 @@ const PanelManager = {
// 添加自定义代理配置 // 添加自定义代理配置
configs.forEach(config => { configs.forEach(config => {
if (config.proxyType !== 'direct' && config.proxyType !== 'system') { if (config.proxyType !== 'direct' && config.proxyType !== 'system') {
const isActive = currentProxy.currentMode === 'fixed_servers' && config.enabled; // 判断是否激活:当前模式为 fixed_servers 且配置已启用
const proxyIcon = config.proxyType === 'pac_script' ? '📜' : '🌐'; const isActive = currentProxy.currentMode === 'fixed_servers' &&
config.enabled;
// 构建 title 提示信息 const tooltipText = config.proxyType === 'pac_script'
let tooltipText; ? 'PAC Script'
if (config.proxyType === 'pac_script') { : `${(config.proxyType || 'HTTP').toUpperCase()} ${config.host || ''}:${config.port || ''}`;
tooltipText = 'PAC Script';
} else { const proxyIcon = config.proxyType === 'pac_script' ? '📜' : '🌐';
const scheme = config.scheme ? `${config.scheme.toUpperCase()} ` : '';
tooltipText = `${scheme}${config.host}:${config.port}`;
}
html += ` html += `
<div class="proxy-item ${isActive ? 'active' : ''}" <div class="proxy-item ${isActive ? 'active' : ''}"
data-id="${config.id}" data-id="${config.id}"
title="${tooltipText}"> title="${tooltipText}">
<span>${proxyIcon}</span> <span style="color: ${isActive ? '#ff6b00' : '#666'}">${proxyIcon}</span>
<span>${config.name || '未命名代理'}</span> <span>${config.name || '未命名代理'}</span>
${isActive ? '<div class="proxy-status"></div>' : ''} <img src="${YAK_ICON_URL}" class="watermark-icon" alt="" />
</div> </div>
`; `;
} }
}); });
// 添加操作按钮
html += ` html += `
<div class="divider"></div> <div class="add-proxy">
<div class="action-button add-proxy">
<span>➕</span> <span>➕</span>
<span>添加代理</span> <span>添加代理...</span>
</div> </div>
<div class="action-button settings"> <div class="settings">
<span>⚙️</span> <span>👨‍💻</span>
<span>设置</span> <span>选项</span>
</div> </div>
`; `;
@@ -770,119 +681,6 @@ const PanelManager = {
console.error('Error opening options page:', error); console.error('Error opening options page:', error);
} }
}); });
},
_initDragFeature(header, panel) {
let isDragging = false;
let startY = 0;
let startTop = 0;
let rafId = null;
const updatePosition = (e) => {
if (!isDragging) return;
const deltaY = e.clientY - startY;
const newTop = startTop + deltaY;
// 限制拖动范围在视窗内
const maxTop = window.innerHeight - panel.offsetHeight;
const boundedTop = Math.max(0, Math.min(newTop, maxTop));
// 保持水平位置不变,只改变垂直位置
panel.style.top = `${boundedTop}px`;
panel.style.transform = 'translateY(0)'; // 移除默认的 translateY(-50%)
};
const onMouseDown = (e) => {
// 如果点击时是展开状态,则处理展开/收起
if (panel.classList.contains('expanded')) {
panel.classList.remove('expanded');
return;
}
if (e.button !== 0) return; // 只响应左键
isDragging = true;
startY = e.clientY;
// 获取当前实际位置
const rect = panel.getBoundingClientRect();
startTop = rect.top;
// 开始拖动时固定当前位置
panel.style.top = `${startTop}px`;
panel.style.transform = 'translateY(0)';
// 添加拖动时的视觉反馈
panel.style.transition = 'none';
panel.classList.add('dragging');
// 防止文本选择
e.preventDefault();
};
const onMouseMove = (e) => {
if (!isDragging) return;
// 使用 requestAnimationFrame 优化性能
if (rafId) cancelAnimationFrame(rafId);
rafId = requestAnimationFrame(() => updatePosition(e));
};
const onMouseUp = () => {
if (!isDragging) return;
isDragging = false;
// 清理
if (rafId) {
cancelAnimationFrame(rafId);
rafId = null;
}
panel.classList.remove('dragging');
panel.style.transition = '';
// 保存位置
const top = panel.getBoundingClientRect().top;
const viewportHeight = window.innerHeight;
const percentage = (top / viewportHeight) * 100;
localStorage.setItem('yakitProxyPanelPosition', percentage.toString());
};
// 修改事件监听
header.addEventListener('mousedown', onMouseDown);
document.addEventListener('mousemove', onMouseMove, { passive: true });
document.addEventListener('mouseup', onMouseUp);
// 恢复保存的位置
const savedPosition = localStorage.getItem('yakitProxyPanelPosition');
if (savedPosition) {
const top = (parseFloat(savedPosition) / 100) * window.innerHeight;
panel.style.top = `${top}px`;
panel.style.transform = 'translateY(0)';
}
},
_initAutoCollapse(panel) {
let leaveTimer = null;
const onMouseLeave = () => {
if (panel.classList.contains('expanded')) {
leaveTimer = setTimeout(() => {
panel.classList.remove('expanded');
}, 300); // 300ms 延迟,避免意外触发
}
};
const onMouseEnter = () => {
if (leaveTimer) {
clearTimeout(leaveTimer);
leaveTimer = null;
}
};
panel.addEventListener('mouseleave', onMouseLeave);
panel.addEventListener('mouseenter', onMouseEnter);
} }
}; };
@@ -913,4 +711,3 @@ window.addEventListener('load', () => {
console.log("Document readyState:", document.readyState); console.log("Document readyState:", document.readyState);
console.log("Document body exists:", !!document.body); console.log("Document body exists:", !!document.body);
console.log("Document documentElement exists:", !!document.documentElement); console.log("Document documentElement exists:", !!document.documentElement);
+2 -2
View File
@@ -43,9 +43,9 @@ export class ProxySettings {
]); ]);
} }
// 确保日志存储已初始化 // 确保日志存储已初始化
const logs = await proxyStore.getLogs(); const logs = await proxyStore.getLogs(); // 使用 getLogs 而不是 getProxyLogs
if (!logs || logs.length === 0) { if (!logs || logs.length === 0) {
await proxyStore.clearLogs(); await proxyStore.clearLogs(); // 初始化日志存储
} }
} }
} }
+4 -8
View File
@@ -237,25 +237,21 @@ export const ProxySwitch: React.FC<ProxySwitchProps> = () => {
const menuItems: MenuProps['items'] = [ const menuItems: MenuProps['items'] = [
...FIXED_MODES.map(mode => ({ ...FIXED_MODES.map(mode => ({
key: mode.key, key: mode.key,
icon: <span className="menu-icon" style={{ icon: <span className="menu-icon" style={{ color: mode.color }}>{mode.icon}</span>,
color: currentMode === mode.key ? 'var(--yakit-primary)' : mode.color label: mode.name,
}}>{mode.icon}</span>,
label: `${mode.name}${currentMode === mode.key ? ' ✅' : ''}`,
className: `${currentMode === mode.key ? 'menu-item-selected' : ''} ${isLoading ? 'menu-item-loading' : ''}`, className: `${currentMode === mode.key ? 'menu-item-selected' : ''} ${isLoading ? 'menu-item-loading' : ''}`,
title: mode.name.replace(/[\[\]]/g, '') title: mode.name.replace(/[\[\]]/g, '')
})), })),
{ type: 'divider' }, { type: 'divider' },
...customProxies.map(proxy => ({ ...customProxies.map(proxy => ({
key: proxy.key, key: proxy.key,
icon: <span className="menu-icon" style={{ icon: <span className="menu-icon" style={{ color: proxy.color }}>
color: currentMode === proxy.key ? 'var(--yakit-primary)' : proxy.color
}}>
{proxy.config.proxyType === 'pac_script' ? '📜' : <GlobalOutlined />} {proxy.config.proxyType === 'pac_script' ? '📜' : <GlobalOutlined />}
</span>, </span>,
label: <span style={{ label: <span style={{
color: currentMode === proxy.key ? 'var(--yakit-primary)' : 'inherit', color: currentMode === proxy.key ? 'var(--yakit-primary)' : 'inherit',
opacity: isLoading ? 0.7 : 1 opacity: isLoading ? 0.7 : 1
}}>{proxy.name}{currentMode === proxy.key ? ' ✅' : ''}</span>, }}>{proxy.name}</span>,
className: `${currentMode === proxy.key ? 'menu-item-selected' : ''} ${isLoading ? 'menu-item-loading' : ''}`, className: `${currentMode === proxy.key ? 'menu-item-selected' : ''} ${isLoading ? 'menu-item-loading' : ''}`,
title: proxy.config.scheme title: proxy.config.scheme
? `${proxy.config.scheme.toUpperCase()} ${proxy.config.host}:${proxy.config.port}` ? `${proxy.config.scheme.toUpperCase()} ${proxy.config.host}:${proxy.config.port}`