feat(hotmail): 添加 Hotmail 账号池的展开/收起功能及持久化状态支持
This commit is contained in:
@@ -798,6 +798,20 @@ header {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section-collapse-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-collapse-body[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#btn-toggle-hotmail-section {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.ip-proxy-fold {
|
.ip-proxy-fold {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
+64
-60
@@ -658,6 +658,8 @@
|
|||||||
<span class="section-label">Hotmail 账号池</span>
|
<span class="section-label">Hotmail 账号池</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="section-mini-actions">
|
<div class="section-mini-actions">
|
||||||
|
<button id="btn-toggle-hotmail-section" class="btn btn-ghost btn-xs" type="button"
|
||||||
|
aria-expanded="false" aria-controls="hotmail-section-body">展开设置</button>
|
||||||
<button id="btn-toggle-hotmail-form" class="btn btn-outline btn-xs" type="button"
|
<button id="btn-toggle-hotmail-form" class="btn btn-outline btn-xs" type="button"
|
||||||
aria-expanded="false">添加账号</button>
|
aria-expanded="false">添加账号</button>
|
||||||
<button id="btn-hotmail-usage-guide" class="btn btn-ghost btn-xs" type="button">使用教程</button>
|
<button id="btn-hotmail-usage-guide" class="btn btn-ghost btn-xs" type="button">使用教程</button>
|
||||||
@@ -667,71 +669,73 @@
|
|||||||
aria-expanded="false">展开列表</button>
|
aria-expanded="false">展开列表</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="data-row" id="row-hotmail-service-mode">
|
<div id="hotmail-section-body" class="section-collapse-body" hidden>
|
||||||
<span class="data-label">接码模式</span>
|
<div class="data-row" id="row-hotmail-service-mode">
|
||||||
<div id="hotmail-service-mode-group" class="choice-group" role="group" aria-label="Hotmail 接码模式">
|
<span class="data-label">接码模式</span>
|
||||||
<button type="button" class="choice-btn" data-hotmail-service-mode="remote">API对接</button>
|
<div id="hotmail-service-mode-group" class="choice-group" role="group" aria-label="Hotmail 接码模式">
|
||||||
<button type="button" class="choice-btn" data-hotmail-service-mode="local">本地助手</button>
|
<button type="button" class="choice-btn" data-hotmail-service-mode="remote">API对接</button>
|
||||||
</div>
|
<button type="button" class="choice-btn" data-hotmail-service-mode="local">本地助手</button>
|
||||||
</div>
|
|
||||||
<div class="data-row" id="row-hotmail-remote-base-url">
|
|
||||||
<span class="data-label">API对接</span>
|
|
||||||
<input type="text" id="input-hotmail-remote-base-url" class="data-input mono"
|
|
||||||
placeholder="微软邮箱 API 对接模式无需填写地址" />
|
|
||||||
</div>
|
|
||||||
<div class="data-row" id="row-hotmail-local-base-url" style="display:none;">
|
|
||||||
<span class="data-label">本地助手</span>
|
|
||||||
<input type="text" id="input-hotmail-local-base-url" class="data-input mono"
|
|
||||||
placeholder="http://127.0.0.1:17373" />
|
|
||||||
</div>
|
|
||||||
<div id="hotmail-form-shell" class="account-pool-form-shell" hidden>
|
|
||||||
<div class="data-row">
|
|
||||||
<span class="data-label">邮箱</span>
|
|
||||||
<input type="text" id="input-hotmail-email" class="data-input" placeholder="name@hotmail.com" />
|
|
||||||
</div>
|
|
||||||
<div class="data-row">
|
|
||||||
<span class="data-label">客户端 ID</span>
|
|
||||||
<input type="text" id="input-hotmail-client-id" class="data-input mono" placeholder="微软应用客户端 ID" />
|
|
||||||
</div>
|
|
||||||
<div class="data-row">
|
|
||||||
<span class="data-label">邮箱密码</span>
|
|
||||||
<div class="input-with-icon">
|
|
||||||
<input type="password" id="input-hotmail-password" class="data-input data-input-with-icon"
|
|
||||||
placeholder="可选,仅用于记录" />
|
|
||||||
<button id="btn-toggle-hotmail-password" class="input-icon-btn" type="button"
|
|
||||||
data-password-toggle="input-hotmail-password" data-show-label="显示 Hotmail 密码"
|
|
||||||
data-hide-label="隐藏 Hotmail 密码" aria-label="显示 Hotmail 密码" title="显示 Hotmail 密码"></button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="data-row">
|
<div class="data-row" id="row-hotmail-remote-base-url">
|
||||||
<span class="data-label">刷新令牌</span>
|
<span class="data-label">API对接</span>
|
||||||
<div class="input-with-icon">
|
<input type="text" id="input-hotmail-remote-base-url" class="data-input mono"
|
||||||
<input type="password" id="input-hotmail-refresh-token" class="data-input data-input-with-icon mono"
|
placeholder="微软邮箱 API 对接模式无需填写地址" />
|
||||||
placeholder="必填,粘贴刷新令牌(refresh token)" />
|
</div>
|
||||||
<button id="btn-toggle-hotmail-refresh-token" class="input-icon-btn" type="button"
|
<div class="data-row" id="row-hotmail-local-base-url" style="display:none;">
|
||||||
data-password-toggle="input-hotmail-refresh-token" data-show-label="显示 Hotmail 刷新令牌"
|
<span class="data-label">本地助手</span>
|
||||||
data-hide-label="隐藏 Hotmail 刷新令牌" aria-label="显示 Hotmail 刷新令牌"
|
<input type="text" id="input-hotmail-local-base-url" class="data-input mono"
|
||||||
title="显示 Hotmail 刷新令牌"></button>
|
placeholder="http://127.0.0.1:17373" />
|
||||||
|
</div>
|
||||||
|
<div id="hotmail-form-shell" class="account-pool-form-shell" hidden>
|
||||||
|
<div class="data-row">
|
||||||
|
<span class="data-label">邮箱</span>
|
||||||
|
<input type="text" id="input-hotmail-email" class="data-input" placeholder="name@hotmail.com" />
|
||||||
|
</div>
|
||||||
|
<div class="data-row">
|
||||||
|
<span class="data-label">客户端 ID</span>
|
||||||
|
<input type="text" id="input-hotmail-client-id" class="data-input mono" placeholder="微软应用客户端 ID" />
|
||||||
|
</div>
|
||||||
|
<div class="data-row">
|
||||||
|
<span class="data-label">邮箱密码</span>
|
||||||
|
<div class="input-with-icon">
|
||||||
|
<input type="password" id="input-hotmail-password" class="data-input data-input-with-icon"
|
||||||
|
placeholder="可选,仅用于记录" />
|
||||||
|
<button id="btn-toggle-hotmail-password" class="input-icon-btn" type="button"
|
||||||
|
data-password-toggle="input-hotmail-password" data-show-label="显示 Hotmail 密码"
|
||||||
|
data-hide-label="隐藏 Hotmail 密码" aria-label="显示 Hotmail 密码" title="显示 Hotmail 密码"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="data-row">
|
||||||
|
<span class="data-label">刷新令牌</span>
|
||||||
|
<div class="input-with-icon">
|
||||||
|
<input type="password" id="input-hotmail-refresh-token" class="data-input data-input-with-icon mono"
|
||||||
|
placeholder="必填,粘贴刷新令牌(refresh token)" />
|
||||||
|
<button id="btn-toggle-hotmail-refresh-token" class="input-icon-btn" type="button"
|
||||||
|
data-password-toggle="input-hotmail-refresh-token" data-show-label="显示 Hotmail 刷新令牌"
|
||||||
|
data-hide-label="隐藏 Hotmail 刷新令牌" aria-label="显示 Hotmail 刷新令牌"
|
||||||
|
title="显示 Hotmail 刷新令牌"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="data-row hotmail-actions-row">
|
||||||
|
<span class="data-label"></span>
|
||||||
|
<div class="data-inline account-pool-actions-inline">
|
||||||
|
<button id="btn-add-hotmail-account" class="btn btn-primary btn-sm" type="button">添加账号</button>
|
||||||
|
<button id="btn-import-hotmail-accounts" class="btn btn-outline btn-sm account-pool-import-action"
|
||||||
|
type="button">批量导入</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="data-row hotmail-import-row">
|
||||||
|
<span class="data-label">批量导入</span>
|
||||||
|
<div class="hotmail-import-box">
|
||||||
|
<textarea id="input-hotmail-import" class="data-textarea mono"
|
||||||
|
placeholder="账号----密码----客户端ID----刷新令牌 name@hotmail.com----password----client-id----refresh-token"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="data-row hotmail-actions-row">
|
<div id="hotmail-list-shell" class="hotmail-list-shell is-collapsed">
|
||||||
<span class="data-label"></span>
|
<div id="hotmail-accounts-list" class="hotmail-accounts-list"></div>
|
||||||
<div class="data-inline account-pool-actions-inline">
|
|
||||||
<button id="btn-add-hotmail-account" class="btn btn-primary btn-sm" type="button">添加账号</button>
|
|
||||||
<button id="btn-import-hotmail-accounts" class="btn btn-outline btn-sm account-pool-import-action"
|
|
||||||
type="button">批量导入</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="data-row hotmail-import-row">
|
|
||||||
<span class="data-label">批量导入</span>
|
|
||||||
<div class="hotmail-import-box">
|
|
||||||
<textarea id="input-hotmail-import" class="data-textarea mono"
|
|
||||||
placeholder="账号----密码----客户端ID----刷新令牌 name@hotmail.com----password----client-id----refresh-token"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="hotmail-list-shell" class="hotmail-list-shell is-collapsed">
|
|
||||||
<div id="hotmail-accounts-list" class="hotmail-accounts-list"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="mail2925-section" class="data-card hotmail-card" style="display:none;">
|
<div id="mail2925-section" class="data-card hotmail-card" style="display:none;">
|
||||||
|
|||||||
@@ -190,6 +190,8 @@ const cloudflareTempEmailSection = document.getElementById('cloudflare-temp-emai
|
|||||||
const btnCloudflareTempEmailUsageGuide = document.getElementById('btn-cloudflare-temp-email-usage-guide');
|
const btnCloudflareTempEmailUsageGuide = document.getElementById('btn-cloudflare-temp-email-usage-guide');
|
||||||
const btnCloudflareTempEmailGithub = document.getElementById('btn-cloudflare-temp-email-github');
|
const btnCloudflareTempEmailGithub = document.getElementById('btn-cloudflare-temp-email-github');
|
||||||
const hotmailSection = document.getElementById('hotmail-section');
|
const hotmailSection = document.getElementById('hotmail-section');
|
||||||
|
const btnToggleHotmailSection = document.getElementById('btn-toggle-hotmail-section');
|
||||||
|
const hotmailSectionBody = document.getElementById('hotmail-section-body');
|
||||||
const mail2925Section = document.getElementById('mail2925-section');
|
const mail2925Section = document.getElementById('mail2925-section');
|
||||||
const luckmailSection = document.getElementById('luckmail-section');
|
const luckmailSection = document.getElementById('luckmail-section');
|
||||||
const icloudSection = document.getElementById('icloud-section');
|
const icloudSection = document.getElementById('icloud-section');
|
||||||
@@ -372,6 +374,7 @@ const PLUS_CONTRIBUTION_ACCOUNT_CREDIT = 5;
|
|||||||
const PLUS_CONTRIBUTION_DONATION_CREDIT = 20;
|
const PLUS_CONTRIBUTION_DONATION_CREDIT = 20;
|
||||||
const HOTMAIL_SERVICE_MODE_REMOTE = 'remote';
|
const HOTMAIL_SERVICE_MODE_REMOTE = 'remote';
|
||||||
const HOTMAIL_SERVICE_MODE_LOCAL = 'local';
|
const HOTMAIL_SERVICE_MODE_LOCAL = 'local';
|
||||||
|
const HOTMAIL_SECTION_EXPANDED_STORAGE_KEY = 'multipage-hotmail-section-expanded';
|
||||||
const ICLOUD_PROVIDER = 'icloud';
|
const ICLOUD_PROVIDER = 'icloud';
|
||||||
const GMAIL_PROVIDER = 'gmail';
|
const GMAIL_PROVIDER = 'gmail';
|
||||||
const GMAIL_ALIAS_GENERATOR = 'gmail-alias';
|
const GMAIL_ALIAS_GENERATOR = 'gmail-alias';
|
||||||
@@ -649,6 +652,7 @@ let settingsAutoSaveTimer = null;
|
|||||||
let settingsSaveRevision = 0;
|
let settingsSaveRevision = 0;
|
||||||
let cloudflareDomainEditMode = false;
|
let cloudflareDomainEditMode = false;
|
||||||
let cloudflareTempEmailDomainEditMode = false;
|
let cloudflareTempEmailDomainEditMode = false;
|
||||||
|
let hotmailSectionExpanded = false;
|
||||||
let modalChoiceResolver = null;
|
let modalChoiceResolver = null;
|
||||||
let currentModalActions = [];
|
let currentModalActions = [];
|
||||||
let modalResultBuilder = null;
|
let modalResultBuilder = null;
|
||||||
@@ -2486,6 +2490,56 @@ function setHotmailServiceMode(mode) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readHotmailSectionExpanded() {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(HOTMAIL_SECTION_EXPANDED_STORAGE_KEY) === '1';
|
||||||
|
} catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function persistHotmailSectionExpanded(expanded) {
|
||||||
|
try {
|
||||||
|
if (expanded) {
|
||||||
|
localStorage.setItem(HOTMAIL_SECTION_EXPANDED_STORAGE_KEY, '1');
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(HOTMAIL_SECTION_EXPANDED_STORAGE_KEY);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Keep the current session state even if storage is unavailable.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateHotmailSectionExpandedUI() {
|
||||||
|
const useHotmail = selectMailProvider?.value === 'hotmail-api';
|
||||||
|
const expanded = useHotmail && hotmailSectionExpanded;
|
||||||
|
if (hotmailSectionBody) {
|
||||||
|
hotmailSectionBody.hidden = !expanded;
|
||||||
|
}
|
||||||
|
if (btnToggleHotmailSection) {
|
||||||
|
btnToggleHotmailSection.textContent = expanded ? '收起设置' : '展开设置';
|
||||||
|
btnToggleHotmailSection.title = expanded ? '收起 Hotmail 账号池设置' : '展开 Hotmail 账号池设置';
|
||||||
|
btnToggleHotmailSection.setAttribute('aria-expanded', String(expanded));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHotmailSectionExpanded(expanded, options = {}) {
|
||||||
|
const { persist = true } = options;
|
||||||
|
hotmailSectionExpanded = Boolean(expanded);
|
||||||
|
updateHotmailSectionExpandedUI();
|
||||||
|
if (persist) {
|
||||||
|
persistHotmailSectionExpanded(hotmailSectionExpanded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleHotmailSectionExpanded() {
|
||||||
|
setHotmailSectionExpanded(!hotmailSectionExpanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initHotmailSectionExpandedState() {
|
||||||
|
setHotmailSectionExpanded(readHotmailSectionExpanded(), { persist: false });
|
||||||
|
}
|
||||||
|
|
||||||
function updateAccountRunHistorySettingsUI() {
|
function updateAccountRunHistorySettingsUI() {
|
||||||
if (!rowAccountRunHistoryHelperBaseUrl) {
|
if (!rowAccountRunHistoryHelperBaseUrl) {
|
||||||
return;
|
return;
|
||||||
@@ -4018,6 +4072,9 @@ function updateMailProviderUI() {
|
|||||||
if (hotmailSection) {
|
if (hotmailSection) {
|
||||||
hotmailSection.style.display = useHotmail ? '' : 'none';
|
hotmailSection.style.display = useHotmail ? '' : 'none';
|
||||||
}
|
}
|
||||||
|
if (typeof updateHotmailSectionExpandedUI === 'function') {
|
||||||
|
updateHotmailSectionExpandedUI();
|
||||||
|
}
|
||||||
if (mail2925Section) {
|
if (mail2925Section) {
|
||||||
mail2925Section.style.display = useMail2925AccountPool ? '' : 'none';
|
mail2925Section.style.display = useMail2925AccountPool ? '' : 'none';
|
||||||
}
|
}
|
||||||
@@ -5217,6 +5274,18 @@ btnToggleIpProxySection?.addEventListener('click', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
btnToggleHotmailSection?.addEventListener('click', () => {
|
||||||
|
toggleHotmailSectionExpanded();
|
||||||
|
});
|
||||||
|
|
||||||
|
btnToggleHotmailForm?.addEventListener('click', () => {
|
||||||
|
setHotmailSectionExpanded(true);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
btnToggleHotmailList?.addEventListener('click', () => {
|
||||||
|
setHotmailSectionExpanded(true);
|
||||||
|
}, true);
|
||||||
|
|
||||||
btnMailLogin?.addEventListener('click', async () => {
|
btnMailLogin?.addEventListener('click', async () => {
|
||||||
const config = getMailProviderLoginConfig();
|
const config = getMailProviderLoginConfig();
|
||||||
const loginUrl = getMailProviderLoginUrl();
|
const loginUrl = getMailProviderLoginUrl();
|
||||||
@@ -7040,6 +7109,7 @@ bindPasswordVisibilityToggles();
|
|||||||
initTheme();
|
initTheme();
|
||||||
initHotmailListExpandedState();
|
initHotmailListExpandedState();
|
||||||
initMail2925ListExpandedState();
|
initMail2925ListExpandedState();
|
||||||
|
initHotmailSectionExpandedState();
|
||||||
if (typeof initIpProxySectionExpandedState === 'function') {
|
if (typeof initIpProxySectionExpandedState === 'function') {
|
||||||
initIpProxySectionExpandedState();
|
initIpProxySectionExpandedState();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ const test = require('node:test');
|
|||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
|
const sidepanelSource = fs.readFileSync('sidepanel/sidepanel.js', 'utf8');
|
||||||
|
|
||||||
function createAccountPoolUiStub() {
|
function createAccountPoolUiStub() {
|
||||||
return {
|
return {
|
||||||
createAccountPoolFormController({
|
createAccountPoolFormController({
|
||||||
@@ -60,11 +62,25 @@ test('sidepanel loads hotmail manager before sidepanel bootstrap', () => {
|
|||||||
|
|
||||||
test('sidepanel html contains collapsible hotmail form controls', () => {
|
test('sidepanel html contains collapsible hotmail form controls', () => {
|
||||||
const html = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
|
const html = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
|
||||||
|
assert.match(html, /id="btn-toggle-hotmail-section"/);
|
||||||
|
assert.match(html, /aria-controls="hotmail-section-body"/);
|
||||||
|
assert.match(html, /id="hotmail-section-body" class="section-collapse-body" hidden/);
|
||||||
assert.match(html, /id="btn-toggle-hotmail-form"/);
|
assert.match(html, /id="btn-toggle-hotmail-form"/);
|
||||||
assert.match(html, /id="hotmail-form-shell"/);
|
assert.match(html, /id="hotmail-form-shell"/);
|
||||||
assert.match(html, /id="btn-import-hotmail-accounts"[^>]*>批量导入</);
|
assert.match(html, /id="btn-import-hotmail-accounts"[^>]*>批量导入</);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('sidepanel keeps hotmail account pool behind a persisted section collapse', () => {
|
||||||
|
assert.match(sidepanelSource, /HOTMAIL_SECTION_EXPANDED_STORAGE_KEY = 'multipage-hotmail-section-expanded'/);
|
||||||
|
assert.match(sidepanelSource, /let hotmailSectionExpanded = false/);
|
||||||
|
assert.match(sidepanelSource, /function updateHotmailSectionExpandedUI\(\)/);
|
||||||
|
assert.match(sidepanelSource, /hotmailSectionBody\.hidden = !expanded/);
|
||||||
|
assert.match(sidepanelSource, /btnToggleHotmailSection\.setAttribute\('aria-expanded', String\(expanded\)\)/);
|
||||||
|
assert.match(sidepanelSource, /btnToggleHotmailSection\?\.addEventListener\('click', \(\) => \{\s*toggleHotmailSectionExpanded\(\)/);
|
||||||
|
assert.match(sidepanelSource, /btnToggleHotmailForm\?\.addEventListener\('click', \(\) => \{\s*setHotmailSectionExpanded\(true\)/);
|
||||||
|
assert.match(sidepanelSource, /initHotmailSectionExpandedState\(\)/);
|
||||||
|
});
|
||||||
|
|
||||||
test('hotmail manager exposes a factory and renders empty state', () => {
|
test('hotmail manager exposes a factory and renders empty state', () => {
|
||||||
const source = fs.readFileSync('sidepanel/hotmail-manager.js', 'utf8');
|
const source = fs.readFileSync('sidepanel/hotmail-manager.js', 'utf8');
|
||||||
const windowObject = {
|
const windowObject = {
|
||||||
|
|||||||
Reference in New Issue
Block a user