Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/webui/src/i18n/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ const enUS: Record<string, string> = {
'uid.toast_removed': 'Removed',
'uid.toast_remove_failed': 'Failed to remove: ',
'uid.toast_load_apps_failed': 'Failed to load app list: ',
'uid.btn_add_selected': 'Add Selected ({count})',
'uid.btn_add_selected': 'Confirm ({count})',
'uid.toast_added_count': 'Successfully added {count} apps',
'uid.no_apps_found': 'No apps found',

Expand Down
2 changes: 1 addition & 1 deletion src/webui/src/i18n/ur-PK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ const urPK: Record<string, string> = {
'uid.toast_removed': 'ہٹا دیا گیا',
'uid.toast_remove_failed': 'ہٹانے میں ناکام: ',
'uid.toast_load_apps_failed': 'ایپ لسٹ لوڈ کرنے میں ناکام: ',
'uid.btn_add_selected': 'منتخب شامل کریں ({count})',
'uid.btn_add_selected': 'تصدیق کریں ({count})',
'uid.toast_added_count': '{count} ایپس کامیابی سے شامل ہو گئیں',
'uid.no_apps_found': 'کوئی ایپس نہیں ملیں',

Expand Down
2 changes: 1 addition & 1 deletion src/webui/src/i18n/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ const zhCN: Record<string, string> = {
'uid.toast_removed': '已移除',
'uid.toast_remove_failed': '移除失败: ',
'uid.toast_load_apps_failed': '加载应用列表失败: ',
'uid.btn_add_selected': '添加选中 ({count})',
'uid.btn_add_selected': '确认 ({count})',
'uid.toast_added_count': '成功添加 {count} 个应用',
'uid.no_apps_found': '没有找到应用',

Expand Down
41 changes: 41 additions & 0 deletions src/webui/src/styles/components/mdui-overrides.css
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,24 @@ mdui-dialog#confirm-dialog::part(panel) {
width: 90% !important;
}

/* 关于对话框 - 从底部滑入动画 */
mdui-dialog#about-dialog::part(panel) {
background-color: var(--monet-surface-container-high, var(--mdui-color-surface-container-high)) !important;
animation: slideUpIn 250ms cubic-bezier(0.2, 0, 0, 1) forwards;
transform-origin: center bottom;
}

@keyframes slideUpIn {
from {
opacity: 0;
transform: translateY(100%);
}
to {
opacity: 1;
transform: translateY(0);
}
}

/* ==================== 列表 ==================== */

mdui-list {
Expand Down Expand Up @@ -567,4 +585,27 @@ mdui-divider {
/* 将 snackbar 提升到底部导航栏上方 (底部导航栏高度约 80px) */
mdui-snackbar[placement="bottom"] {
bottom: 88px !important;
}

/* ==================== 当前节点标签文字颜色 ==================== */

/* 应用浅色模式:半透明白色文字 */
.mdui-theme-light .current-tag-text {
color: rgba(255, 255, 255, 0.85) !important;
}

/* 应用深色模式:半透明黑色文字 */
.mdui-theme-dark .current-tag-text {
color: rgba(0, 0, 0, 0.75) !important;
}

/* 应用自动模式:跟随系统深浅色模式 */
.mdui-theme-auto .current-tag-text {
color: rgba(255, 255, 255, 0.85) !important;
}

@media (prefers-color-scheme: dark) {
.mdui-theme-auto .current-tag-text {
color: rgba(0, 0, 0, 0.75) !important;
}
}
64 changes: 57 additions & 7 deletions src/webui/src/ui/app-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class AppPageManager {
proxyMode: string;
proxyApps: ProxyAppConfig[];
selectedApps: Map<string, AppInfo>;
originalProxyApps: Map<string, AppInfo>;
users: UserInfo[];
currentUserId: string;
showSystemApps: boolean;
Expand All @@ -42,7 +43,8 @@ export class AppPageManager {
this.allApps = [];
this.proxyMode = 'blacklist';
this.proxyApps = [];
this.selectedApps = new Map(); // 用于多选, key: "userId:packageName"
this.selectedApps = new Map();
this.originalProxyApps = new Map();
this.users = [];
this.currentUserId = '0';
this.showSystemApps = false; // 默认不显示系统应用 (-3 only)
Expand Down Expand Up @@ -326,6 +328,12 @@ export class AppPageManager {
const listEl = document.getElementById('app-selector-list');
const addSelectedBtn = document.getElementById('app-selector-add-selected');

// 清空搜索输入框并重置筛选状态
const filterInput = document.getElementById('app-selector-search') as HTMLInputElement | null;
if (filterInput) {
filterInput.value = '';
}

// 加载用户列表
const userSelect = document.getElementById('app-selector-user') as any;
if (userSelect) {
Expand All @@ -343,6 +351,21 @@ export class AppPageManager {

// 清空选中状态
this.selectedApps.clear();
this.originalProxyApps.clear();

// 预填充已在代理列表中的应用
for (const proxyApp of this.proxyApps) {
const key = `${proxyApp.userId}:${proxyApp.packageName}`;
const appInfo: AppInfo = {
packageName: proxyApp.packageName,
userId: proxyApp.userId,
appLabel: proxyApp.appLabel,
icon: proxyApp.icon
};
this.selectedApps.set(key, appInfo);
this.originalProxyApps.set(key, appInfo);
}

this.updateAddSelectedButton();

// 绑定批量添加按钮事件(每次打开都重新绑定)
Expand All @@ -360,7 +383,9 @@ export class AppPageManager {
if (btn) {
const count = this.selectedApps.size;
btn.textContent = I18nService.t('uid.btn_add_selected', { count: String(count) });
btn.disabled = count === 0;
const hasChanges = count > 0 ||
this.originalProxyApps.size !== this.selectedApps.size;
btn.disabled = !hasChanges;
}
}

Expand All @@ -387,24 +412,49 @@ export class AppPageManager {
}

async addSelectedApps(): Promise<void> {
if (this.selectedApps.size === 0) return;
// 找出需要移除的应用(在原始列表中但不在选中列表中)
const appsToRemove: AppInfo[] = [];
for (const [key, app] of this.originalProxyApps) {
if (!this.selectedApps.has(key)) {
appsToRemove.push(app);
}
}

const apps = Array.from(this.selectedApps.values());
// 找出需要添加的应用
const appsToAdd = Array.from(this.selectedApps.values());

for (const app of apps) {
// 移除被取消勾选的应用
for (const app of appsToRemove) {
try {
await AppService.removeProxyApp(app.packageName, app.userId);
} catch (error) {
// 忽略错误
}
}

// 添加新选中的应用
for (const app of appsToAdd) {
try {
await AppService.addProxyApp(app.packageName, app.userId);
} catch (error) {
// 忽略错误(如应用已存在)
}
}

toast(I18nService.t('uid.toast_added_count', { count: String(apps.length) }));
// 根据操作显示提示
if (appsToRemove.length > 0 && appsToAdd.length > 0) {
toast(I18nService.t('uid.toast_added_count', { count: String(appsToAdd.length) }));
} else if (appsToRemove.length > 0) {
toast(I18nService.t('uid.toast_removed'));
} else if (appsToAdd.length > 0) {
toast(I18nService.t('uid.toast_added_count', { count: String(appsToAdd.length) }));
}

// 关闭对话框并刷新列表
const dialog = document.getElementById('app-selector-dialog') as any;
if (dialog) dialog.open = false;
this.selectedApps.clear();
// 清除缓存并强制刷新
this.originalProxyApps.clear();
this.proxyApps = [];
await this.update(true);
}
Expand Down
3 changes: 2 additions & 1 deletion src/webui/src/ui/config-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,8 @@ export class ConfigPageManager {
if (isCurrent) {
const currentTag = document.createElement('span');
currentTag.textContent = I18nService.t('config.status.current');
currentTag.style.cssText = 'font-size: 10px; padding: 1px 4px; border-radius: 4px; background: var(--mdui-color-primary); color: #ffffff;';
currentTag.className = 'current-tag-text';
currentTag.style.cssText = 'font-size: 10px; padding: 1px 4px; border-radius: 4px; background: var(--mdui-color-primary);';
protocolLine.appendChild(currentTag);
}

Expand Down
9 changes: 8 additions & 1 deletion src/webui/src/ui/settings-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class SettingsPageManager {
_logsAutoRefreshEnabled: boolean;
_logsAutoRefreshInterval: ReturnType<typeof setInterval> | null;
_logsAutoRefreshMs: number;
lastAppliedThemeMode: string;

constructor(ui: UI) {
this.ui = ui;
Expand Down Expand Up @@ -1037,6 +1038,7 @@ export class SettingsPageManager {
loadThemeSettings(): void {
const savedTheme = localStorage.getItem('theme') || 'auto';
const savedColor = localStorage.getItem('themeColor') || '#6750A4';
this.lastAppliedThemeMode = savedTheme;

// 设置模式选择
const modeGroup = document.getElementById('theme-mode-group') as any;
Expand All @@ -1063,6 +1065,10 @@ export class SettingsPageManager {
}

applyThemeMode(mode) {
if (mode === this.lastAppliedThemeMode) {
return;
}
this.lastAppliedThemeMode = mode;
localStorage.setItem('theme', mode);
setTheme(mode);

Expand Down Expand Up @@ -1264,7 +1270,7 @@ export class SettingsPageManager {
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const html = document.documentElement;

if (savedMonet === 'true' && savedTheme === 'auto') {
if (savedMonet !== 'false' && savedTheme === 'auto') {
// 自动模式 + 莫奈取色开启:使用 KernelSU 注入的变量
html.classList.add('mdui-theme-auto');
html.classList.remove('mdui-theme-light', 'mdui-theme-dark');
Expand Down Expand Up @@ -1336,6 +1342,7 @@ export class SettingsPageManager {

showAboutDialog() {
const dialog = document.createElement('mdui-dialog') as any;
dialog.id = 'about-dialog';
dialog.headline = I18nService.t('settings.about.title');
dialog.innerHTML = `
<div style="text-align: center; padding: 16px 0;">
Expand Down
28 changes: 22 additions & 6 deletions src/webui/src/ui/ui-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,31 @@ export class UI {

applyTheme(theme: string): void {
const html = document.documentElement;
const savedMonet = localStorage.getItem('monetEnabled');
const isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;

// 首先移除所有主题类
// 移除所有主题类
html.classList.remove('mdui-theme-light', 'mdui-theme-dark', 'mdui-theme-auto');

// 添加对应的主题类
html.classList.add(`mdui-theme-${theme}`);

// 同时调用MDUI的setTheme确保组件内部状态正确
setTheme(theme as any);
if (theme === 'light') {
html.classList.add('mdui-theme-light');
setTheme('light');
} else if (theme === 'dark') {
html.classList.add('mdui-theme-dark');
setTheme('dark');
} else {
// 自动模式
const monetEnabled = savedMonet !== 'false';
if (monetEnabled) {
// 莫奈取色开启:使用 mdui-theme-auto
html.classList.add('mdui-theme-auto');
setTheme('auto');
} else {
// 莫奈取色关闭:根据系统偏好设置主题
html.classList.add(isDark ? 'mdui-theme-dark' : 'mdui-theme-light');
setTheme(isDark ? 'dark' : 'light');
}
}
}

setupDialogs(): void {
Expand Down