Переглянути джерело

feat(sidepanel): 更新邮箱状态处理逻辑并增强设置卡片的锁定状态管理

QLHazyCoder 4 місяців тому
батько
коміт
be8e2e25c2
4 змінених файлів з 111 додано та 11 видалено
  1. 15 1
      background.js
  2. 22 0
      sidepanel/sidepanel.css
  3. 12 8
      sidepanel/sidepanel.html
  4. 62 2
      sidepanel/sidepanel.js

+ 15 - 1
background.js

@@ -229,9 +229,13 @@ function broadcastDataUpdate(payload) {
   }).catch(() => { });
 }
 
-async function setEmailState(email) {
+async function setEmailStateSilently(email) {
   await setState({ email });
   broadcastDataUpdate({ email });
+}
+
+async function setEmailState(email) {
+  await setEmailStateSilently(email);
   if (email) {
     await resumeAutoRunIfWaitingForEmail();
   }
@@ -2539,6 +2543,16 @@ async function handleMessage(message, sender) {
     }
 
     // Side panel data updates
+    case 'SET_EMAIL_STATE': {
+      const state = await getState();
+      if (isAutoRunLockedState(state)) {
+        throw new Error('自动流程运行中,当前不能手动修改邮箱。');
+      }
+      const email = String(message.payload?.email || '').trim() || null;
+      await setEmailStateSilently(email);
+      return { ok: true, email };
+    }
+
     case 'SAVE_EMAIL': {
       const state = await getState();
       if (isAutoRunLockedState(state)) {

+ 22 - 0
sidepanel/sidepanel.css

@@ -238,6 +238,20 @@ header {
   box-shadow: var(--shadow-sm);
 }
 
+.data-card.is-locked {
+  position: relative;
+  overflow: hidden;
+}
+
+.data-card.is-locked::after {
+  content: '';
+  position: absolute;
+  inset: 0;
+  border-radius: inherit;
+  background: color-mix(in srgb, var(--bg-base) 18%, transparent);
+  pointer-events: none;
+}
+
 .section-mini-header {
   display: flex;
   align-items: center;
@@ -283,6 +297,10 @@ header {
   min-width: 0;
 }
 
+.data-value-actions {
+  justify-content: space-between;
+}
+
 .input-with-icon {
   position: relative;
   flex: 1;
@@ -307,6 +325,10 @@ header {
   min-width: 0;
 }
 
+.data-value-fill {
+  flex: 1;
+}
+
 .data-value.has-value { color: var(--text-primary); }
 
 .mono {

+ 12 - 8
sidepanel/sidepanel.html

@@ -62,7 +62,7 @@
   </header>
 
   <section id="data-section">
-    <div class="data-card">
+    <div id="settings-card" class="data-card">
       <div class="data-row">
         <span class="data-label">来源</span>
         <select id="select-panel-mode" class="data-select">
@@ -81,7 +81,11 @@
       </div>
       <div class="data-row" id="row-vps-password">
         <span class="data-label">管理密钥</span>
-        <input type="password" id="input-vps-password" class="data-input" placeholder="请输入 CPA 管理密钥" />
+        <div class="input-with-icon">
+          <input type="password" id="input-vps-password" class="data-input data-input-with-icon" placeholder="请输入 CPA 管理密钥" />
+          <button id="btn-toggle-vps-password" class="input-icon-btn" type="button" aria-label="显示管理密钥"
+            title="显示管理密钥"></button>
+        </div>
       </div>
       <div class="data-row" id="row-local-cpa-step9-mode">
         <span class="data-label">本地 CPA</span>
@@ -108,14 +112,11 @@
       </div>
       <div class="data-row">
         <span class="data-label">codex密码</span>
-        <div class="data-inline">
-          <div class="input-with-icon">
-            <input type="password" id="input-password" class="data-input data-input-with-icon"
+        <div class="input-with-icon">
+          <input type="password" id="input-password" class="data-input data-input-with-icon"
               placeholder="codex密码,留空则自动生成" />
             <button id="btn-toggle-password" class="input-icon-btn" type="button" aria-label="显示密码"
               title="显示密码"></button>
-          </div>
-          <button id="btn-save-settings" class="btn btn-outline btn-sm" type="button">保存</button>
         </div>
       </div>
       <div class="data-row">
@@ -186,7 +187,10 @@
       </div>
       <div class="data-row">
         <span class="data-label">回调</span>
-        <span id="display-localhost-url" class="data-value mono truncate">等待中...</span>
+        <div class="data-inline data-value-actions">
+          <span id="display-localhost-url" class="data-value data-value-fill mono truncate">等待中...</span>
+          <button id="btn-save-settings" class="btn btn-outline btn-sm" type="button">保存</button>
+        </div>
       </div>
     </div>
     <div id="hotmail-section" class="data-card hotmail-card" style="display:none;">

+ 62 - 2
sidepanel/sidepanel.js

@@ -11,6 +11,7 @@ const STATUS_ICONS = {
 };
 
 const logArea = document.getElementById('log-area');
+const settingsCard = document.getElementById('settings-card');
 const displayOauthUrl = document.getElementById('display-oauth-url');
 const displayLocalhostUrl = document.getElementById('display-localhost-url');
 const displayStatus = document.getElementById('display-status');
@@ -549,6 +550,48 @@ function setLocalCpaStep9Mode(mode) {
   });
 }
 
+function setSettingsCardLocked(locked) {
+  if (!settingsCard) {
+    return;
+  }
+  settingsCard.classList.toggle('is-locked', locked);
+  settingsCard.toggleAttribute('inert', locked);
+}
+
+async function setRuntimeEmailState(email) {
+  const normalizedEmail = String(email || '').trim() || null;
+  const response = await chrome.runtime.sendMessage({
+    type: 'SET_EMAIL_STATE',
+    source: 'sidepanel',
+    payload: { email: normalizedEmail },
+  });
+
+  if (response?.error) {
+    throw new Error(response.error);
+  }
+
+  return normalizedEmail;
+}
+
+async function clearRegistrationEmail(options = {}) {
+  const { silent = false } = options;
+  if (!inputEmail.value.trim() && !latestState?.email) {
+    return;
+  }
+
+  inputEmail.value = '';
+  syncLatestState({ email: null });
+
+  try {
+    await setRuntimeEmailState(null);
+  } catch (err) {
+    if (!silent) {
+      showToast(`清空邮箱失败:${err.message}`, 'error');
+    }
+    throw err;
+  }
+}
+
 function markSettingsDirty(isDirty = true) {
   settingsDirty = isDirty;
   updateSaveButtonState();
@@ -615,6 +658,9 @@ function applyAutoRunStatus(payload = currentAutoRun) {
   const locked = isAutoRunLockedPhase();
   const paused = isAutoRunPausedPhase();
   const scheduled = isAutoRunScheduledPhase();
+  const settingsCardLocked = scheduled || locked;
+
+  setSettingsCardLocked(settingsCardLocked);
 
   inputRunCount.disabled = currentAutoRun.autoRunning;
   btnAutoRun.disabled = currentAutoRun.autoRunning;
@@ -1915,8 +1961,18 @@ inputEmail.addEventListener('change', async () => {
     return;
   }
   const email = inputEmail.value.trim();
-  if (email) {
-    await chrome.runtime.sendMessage({ type: 'SAVE_EMAIL', source: 'sidepanel', payload: { email } });
+  inputEmail.value = email;
+  try {
+    if (email) {
+      const response = await chrome.runtime.sendMessage({ type: 'SAVE_EMAIL', source: 'sidepanel', payload: { email } });
+      if (response?.error) {
+        throw new Error(response.error);
+      }
+    } else {
+      await setRuntimeEmailState(null);
+    }
+  } catch (err) {
+    showToast(err.message, 'error');
   }
 });
 inputEmail.addEventListener('input', updateButtonStates);
@@ -1953,6 +2009,7 @@ selectMailProvider.addEventListener('change', () => {
 
 selectEmailGenerator.addEventListener('change', () => {
   updateMailProviderUI();
+  clearRegistrationEmail({ silent: true }).catch(() => { });
   markSettingsDirty(true);
   saveSettings({ silent: true }).catch(() => { });
 });
@@ -2140,6 +2197,9 @@ chrome.runtime.onMessage.addListener((message) => {
       if (message.payload.password !== undefined) {
         inputPassword.value = message.payload.password || '';
       }
+      if (message.payload.localCpaStep9Mode !== undefined) {
+        setLocalCpaStep9Mode(message.payload.localCpaStep9Mode);
+      }
       if (message.payload.oauthUrl !== undefined) {
         displayOauthUrl.textContent = message.payload.oauthUrl || '等待中...';
         displayOauthUrl.classList.toggle('has-value', Boolean(message.payload.oauthUrl));