// 设置页:Miuix Preference 分组 + 玻璃条目,含主题/遮罩/亮度/权限/网络交互
// Settings page: Miuix Preference groups + glass items with interactions for
// theme / mask / brightness / permission / network
window.loadSettings = function () {
const page = document.querySelector('[data-page="settings"]');
if (page.dataset.loaded) return; page.dataset.loaded = '1';
page.innerHTML = `
显示
主题
跟随系统
玻璃效果
屏幕亮度
›
背景遮罩
启用背景遮罩
遮罩明暗度
权限
通知使用权(媒体卡)
›
网络
webAPP 服务器地址
›
检查更新
›
关于
导出日志
›
版本 0.1.0›
`;
setupTheme(page);
setupGlass(page);
setupMask(page);
setupNotificationAccess(page);
setupBrightness(page);
setupServerUrl(page);
setupCheckUpdate(page);
setupExportLog(page);
};
// 判断当前是否深色主题(与 mask.js 逻辑一致)
// Whether the current theme is dark (same logic as mask.js)
function isDarkTheme() {
const t = theme.get();
if (t === 'dark') return true;
if (t === 'light') return false;
return matchMedia('(prefers-color-scheme: dark)').matches;
}
// 主题三态循环:跟随系统 → 浅色 → 深色
// Theme tri-state cycle: system → light → dark
function setupTheme(page) {
const state = page.querySelector('#theme-state');
const refresh = () => { state.textContent = theme.label(theme.get()); };
refresh();
page.querySelector('#theme-item').onclick = () => {
theme.cycle();
refresh();
window.mask.apply();
setupMask(page); // 主题切换后重算遮罩项的显示与状态
};
}
// 玻璃效果开关:普通半透明 ↔ 液态玻璃(backdrop-filter 磨砂 + 边缘高光)
// Glass effect toggle: plain translucent vs liquid glass
function setupGlass(page) {
const sw = page.querySelector('#glass-sw');
const refresh = () => sw.classList.toggle('on', glass.enabled());
refresh();
page.querySelector('#glass-item').onclick = () => {
glass.setEnabled(!glass.enabled());
refresh();
};
}
// 背景遮罩:开关 + 明暗度(仅夜间主题显示)
// Wallpaper dim: toggle + opacity (shown only under dark theme)
function setupMask(page) {
const group = page.querySelector('#mask-group');
const maskItem = page.querySelector('#mask-item');
const alphaItem = page.querySelector('#mask-alpha-item');
const sw = page.querySelector('#mask-sw');
const slider = page.querySelector('#mask-slider');
const thumb = slider.querySelector('i');
const dark = isDarkTheme();
const show = dark;
group.style.display = show ? '' : 'none';
maskItem.style.display = show ? '' : 'none';
alphaItem.style.display = show ? '' : 'none';
const refresh = () => {
sw.classList.toggle('on', window.mask.enabled());
const a = window.mask.alpha();
thumb.style.left = (a * 100) + '%';
slider.style.setProperty('--fill', (a * 100) + '%');
};
refresh();
sw.onclick = () => {
window.mask.setEnabled(!window.mask.enabled());
refresh();
};
makeSliderDraggable(slider, (a) => {
window.mask.setAlpha(Math.round(a * 100) / 100);
refresh();
});
}
// 通知使用权授权项:异步查状态,未授权点击跳转系统授权页
// Notification-access item: async state check, tap to open the system grant page
function setupNotificationAccess(page) {
const item = page.querySelector('#notif-access');
const state = page.querySelector('#notif-access-state');
bridge.call('getNotificationAccess').then(granted => {
state.textContent = granted ? '已开启 ✓' : '去开启 ›';
if (granted) state.style.color = 'var(--accent)';
}).catch(() => {});
item.onclick = () => {
bridge.call('requestNotificationAccess').catch(() => {});
};
}
// 屏幕亮度:未授权「修改系统设置」时跳授权页,已授权点击滑块调整系统亮度
// Screen brightness: jump to grant page when lacking WRITE_SETTINGS; adjust via
// slider click once granted
function setupBrightness(page) {
const item = page.querySelector('#brightness-item');
const state = page.querySelector('#brightness-state');
let sliderEl = null;
const renderSlider = (value) => {
if (sliderEl) sliderEl.remove();
sliderEl = document.createElement('span');
sliderEl.className = 'slider brightness-slider';
sliderEl.innerHTML = '';
sliderEl.style.width = '160px';
const pct = value / 255 * 100;
sliderEl.style.setProperty('--fill', pct + '%');
sliderEl.querySelector('i').style.left = pct + '%';
makeSliderDraggable(sliderEl, (ratio) => {
const v = Math.round(ratio * 255);
bridge.call('setSystemBrightness', v).then(() => renderSlider(v)).catch(() => {});
});
item.appendChild(sliderEl);
};
const refresh = () => {
bridge.call('canWriteSettings').then(canWrite => {
if (!canWrite) {
state.textContent = '去授权 ›';
if (sliderEl) { sliderEl.remove(); sliderEl = null; }
} else {
bridge.call('getSystemBrightness').then(v => {
state.textContent = '';
renderSlider(v);
}).catch(() => {});
}
}).catch(() => {});
};
refresh();
item.onclick = () => {
bridge.call('canWriteSettings').then(canWrite => {
if (!canWrite) bridge.call('requestWriteSettings');
}).catch(() => {});
};
}
// webAPP 服务器地址:点击展开输入框,保存后重新拉取清单
// webAPP server URL: expand an input on tap, re-fetch manifest after saving
function setupServerUrl(page) {
const item = page.querySelector('#server-url-item');
const state = page.querySelector('#server-url-state');
let editing = false;
const startEdit = (current) => {
editing = true;
item.innerHTML = '' +
'';
const input = item.querySelector('#server-url-input');
const saveBtn = item.querySelector('#server-url-save');
input.focus();
const save = () => {
const v = input.value.trim();
if (!v) return;
bridge.call('setServerUrl', v).then(() => {
editing = false;
refresh();
}).catch(() => {});
};
saveBtn.onclick = save;
input.onkeydown = (e) => { if (e.key === 'Enter') save(); };
};
const refresh = () => {
bridge.call('getServerUrl').then(url => {
state.textContent = (url || '未设置') + ' ›';
}).catch(() => {});
};
refresh();
item.onclick = () => {
if (editing) return;
bridge.call('getServerUrl').then(startEdit).catch(() => startEdit(''));
};
}
// 检查更新:触发重新拉取 webAPP 清单 + 卡片目录,完成后提示
// Check update: re-fetch the webAPP manifest + card catalog, then show a hint
function setupCheckUpdate(page) {
const item = page.querySelector('#check-update-item');
const state = page.querySelector('#check-update-state');
item.onclick = () => {
state.textContent = '检查中…';
bridge.call('refreshManifest').then(result => {
let r = { added: 0, removed: 0, changed: 0 };
try { r = JSON.parse(result); } catch (e) {}
const parts = [];
if (r.added > 0) parts.push('新增 ' + r.added);
if (r.removed > 0) parts.push('移除 ' + r.removed);
if (r.changed > 0) parts.push('更新 ' + r.changed);
state.textContent = parts.length ? parts.join(',') + ' ›' : '无更新 ›';
}).catch(() => {
state.textContent = '失败 ›';
});
};
}
// 导出日志:点击导出到 Download,显示结果
// Export log: tap to export to Download, show the result
function setupExportLog(page) {
const item = page.querySelector('#export-log-item');
const state = page.querySelector('#export-log-state');
item.onclick = () => {
state.textContent = '导出中…';
bridge.call('exportLog').then(result => {
state.textContent = result + ' ›';
}).catch(() => {
state.textContent = '失败 ›';
});
};
}
// 通用滑块拖动:touch 拖动实时回调(保留 click 兼容桌面调试)
// Generic draggable slider: touch-drag with live callback (click kept for desktop)
function makeSliderDraggable(slider, onRatio) {
let dragging = false;
const ratioAt = (clientX) => {
const rect = slider.getBoundingClientRect();
return Math.min(1, Math.max(0, (clientX - rect.left) / rect.width));
};
slider.addEventListener('touchstart', (e) => {
dragging = true;
onRatio(ratioAt(e.touches[0].clientX));
}, { passive: true });
slider.addEventListener('touchmove', (e) => {
if (dragging) onRatio(ratioAt(e.touches[0].clientX));
}, { passive: true });
slider.addEventListener('touchend', () => { dragging = false; }, { passive: true });
slider.addEventListener('click', (e) => onRatio(ratioAt(e.clientX)));
}