Replace all emoji icons with Lucide SVGs, add accent color picker
- Replace all emoji characters across WebUI with inline Lucide SVG icons for cross-platform consistency (icon paths in icon-paths.js) - Add accent color picker popover with 9 preset colors + custom picker, persisted to localStorage, updates all CSS custom properties - Remove subtab separator line for cleaner look - Color badge icons with accent color for visual pop - Remove processing badge from target cards - Fix hardcoded #4CAF50 in FPS labels and active badges to use CSS vars - Replace CSS content emoji (▶) with pure CSS triangle Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ import { showToast, showConfirm, setTabRefreshing } from '../core/ui.js';
|
||||
import { Modal } from '../core/modal.js';
|
||||
import { CardSection } from '../core/card-sections.js';
|
||||
import { updateTabBadge } from './tabs.js';
|
||||
import { ICON_SETTINGS, ICON_STOP_PLAIN, ICON_START, ICON_PAUSE } from '../core/icons.js';
|
||||
import { ICON_SETTINGS, ICON_STOP_PLAIN, ICON_START, ICON_PAUSE, ICON_CLOCK, ICON_TARGET, ICON_PROFILE, ICON_HELP, ICON_OK } from '../core/icons.js';
|
||||
|
||||
class ProfileEditorModal extends Modal {
|
||||
constructor() { super('profile-editor-modal'); }
|
||||
@@ -88,7 +88,7 @@ function renderProfiles(profiles, runningTargetIds = new Set()) {
|
||||
const container = document.getElementById('profiles-content');
|
||||
|
||||
const items = csProfiles.applySortOrder(profiles.map(p => ({ key: p.id, html: createProfileCard(p, runningTargetIds) })));
|
||||
const toolbar = `<div class="stream-tab-bar"><span class="cs-expand-collapse-group"><button class="btn-expand-collapse" onclick="expandAllProfileSections()" title="${t('section.expand_all')}">⊞</button><button class="btn-expand-collapse" onclick="collapseAllProfileSections()" title="${t('section.collapse_all')}">⊟</button><button class="tutorial-trigger-btn" onclick="startProfilesTutorial()" title="${t('tour.restart')}">?</button></span></div>`;
|
||||
const toolbar = `<div class="stream-tab-bar"><span class="cs-expand-collapse-group"><button class="btn-expand-collapse" onclick="expandAllProfileSections()" title="${t('section.expand_all')}">⊞</button><button class="btn-expand-collapse" onclick="collapseAllProfileSections()" title="${t('section.collapse_all')}">⊟</button><button class="tutorial-trigger-btn" onclick="startProfilesTutorial()" title="${t('tour.restart')}">${ICON_HELP}</button></span></div>`;
|
||||
container.innerHTML = toolbar + csProfiles.render(items);
|
||||
csProfiles.bind();
|
||||
|
||||
@@ -109,7 +109,7 @@ function createProfileCard(profile, runningTargetIds = new Set()) {
|
||||
} else {
|
||||
const parts = profile.conditions.map(c => {
|
||||
if (c.condition_type === 'always') {
|
||||
return `<span class="stream-card-prop">✅ ${t('profiles.condition.always')}</span>`;
|
||||
return `<span class="stream-card-prop">${ICON_OK} ${t('profiles.condition.always')}</span>`;
|
||||
}
|
||||
if (c.condition_type === 'application') {
|
||||
const apps = (c.apps || []).join(', ');
|
||||
@@ -127,7 +127,7 @@ function createProfileCard(profile, runningTargetIds = new Set()) {
|
||||
let lastActivityMeta = '';
|
||||
if (profile.last_activated_at) {
|
||||
const ts = new Date(profile.last_activated_at);
|
||||
lastActivityMeta = `<span class="card-meta" title="${t('profiles.last_activated')}">🕐 ${ts.toLocaleString()}</span>`;
|
||||
lastActivityMeta = `<span class="card-meta" title="${t('profiles.last_activated')}">${ICON_CLOCK} ${ts.toLocaleString()}</span>`;
|
||||
}
|
||||
|
||||
return `
|
||||
@@ -143,7 +143,7 @@ function createProfileCard(profile, runningTargetIds = new Set()) {
|
||||
</div>
|
||||
<div class="card-subtitle">
|
||||
<span class="card-meta">${profile.condition_logic === 'and' ? t('profiles.logic.all') : t('profiles.logic.any')}</span>
|
||||
<span class="card-meta">⚡ ${targetCountText}</span>
|
||||
<span class="card-meta">${ICON_TARGET} ${targetCountText}</span>
|
||||
${lastActivityMeta}
|
||||
</div>
|
||||
<div class="stream-card-props">${condPills}</div>
|
||||
@@ -158,7 +158,7 @@ function createProfileCard(profile, runningTargetIds = new Set()) {
|
||||
</button>`;
|
||||
})() : ''}
|
||||
<button class="btn btn-icon ${profile.enabled ? 'btn-warning' : 'btn-success'}" onclick="toggleProfileEnabled('${profile.id}', ${!profile.enabled})" title="${profile.enabled ? t('profiles.action.disable') : t('profiles.status.active')}">
|
||||
${profile.enabled ? ICON_PAUSE : '▶'}
|
||||
${profile.enabled ? ICON_PAUSE : ICON_START}
|
||||
</button>
|
||||
</div>
|
||||
</div>`;
|
||||
@@ -180,7 +180,7 @@ export async function openProfileEditor(profileId) {
|
||||
await loadProfileTargetChecklist([]);
|
||||
|
||||
if (profileId) {
|
||||
titleEl.textContent = t('profiles.edit');
|
||||
titleEl.innerHTML = `${ICON_PROFILE} ${t('profiles.edit')}`;
|
||||
try {
|
||||
const resp = await fetchWithAuth(`/profiles/${profileId}`);
|
||||
if (!resp.ok) throw new Error('Failed to load profile');
|
||||
@@ -201,7 +201,7 @@ export async function openProfileEditor(profileId) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
titleEl.textContent = t('profiles.add');
|
||||
titleEl.innerHTML = `${ICON_PROFILE} ${t('profiles.add')}`;
|
||||
idInput.value = '';
|
||||
nameInput.value = '';
|
||||
enabledInput.checked = true;
|
||||
|
||||
Reference in New Issue
Block a user