From 68f56d2dc3863f0a70cb520d7985dd3f469c17a1 Mon Sep 17 00:00:00 2001 From: tsw-codes <125425074+tsw-codes@users.noreply.github.com> Date: Sun, 5 Oct 2025 02:06:42 -0400 Subject: [PATCH 1/2] feat: add remove profile picture button to account settings --- src/gui/src/UI/Settings/UITabAccount.js | 22 ++++++++++++++++++++++ src/gui/src/i18n/translations/en.js | 1 + 2 files changed, 23 insertions(+) diff --git a/src/gui/src/UI/Settings/UITabAccount.js b/src/gui/src/UI/Settings/UITabAccount.js index 95de65cf62..aafe4f6ac1 100644 --- a/src/gui/src/UI/Settings/UITabAccount.js +++ b/src/gui/src/UI/Settings/UITabAccount.js @@ -37,6 +37,10 @@ export default { h += `
`; // change password button @@ -150,6 +154,24 @@ export default { }); }) + $el_window.find('.remove-profile-picture').on('click', function (e) { + console.log('Removing profile picture...'); + + // Clear the profile picture from user's profile + update_profile(window.user.username, {picture: null}); + + // Update the profile picture display to default avatar + const defaultAvatar = window.icons['profile.svg']; + $el_window.find('.profile-picture').css('background-image', `url('${defaultAvatar}')`); + $('.profile-image').css('background-image', `url('${defaultAvatar}')`); + $('.profile-image').removeClass('profile-image-has-picture'); + + // Show the remove button (if hidden) + $el_window.find('.remove-profile-picture').show(); + + console.log('Profile picture removed successfully'); + }); + $el_window.on('file_opened', async function(e){ let selected_file = Array.isArray(e.detail) ? e.detail[0] : e.detail; // set profile picture diff --git a/src/gui/src/i18n/translations/en.js b/src/gui/src/i18n/translations/en.js index 613120afc0..f96a1d3c8b 100644 --- a/src/gui/src/i18n/translations/en.js +++ b/src/gui/src/i18n/translations/en.js @@ -238,6 +238,7 @@ const en = { refresh: 'Refresh', release_address_confirmation: `Are you sure you want to release this address?`, remove_from_taskbar:'Remove from Taskbar', + remove_profile_picture: 'Remove Profile Picture', rename: 'Rename', repeat: 'Repeat', replace: 'Replace', From 556dffe013b60104dcf0061dcea52205de99efa4 Mon Sep 17 00:00:00 2001 From: tsw-codes <125425074+tsw-codes@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:39:30 -0500 Subject: [PATCH 2/2] Fixed sidebar header text unreadable with certain theme lightness --- doc/scratch.md | 140 +++++++++++++++++++++++++++ src/gui/src/css/style.css | 4 +- src/gui/src/services/ThemeService.js | 126 +++++++++++++++++++++++- 3 files changed, 267 insertions(+), 3 deletions(-) diff --git a/doc/scratch.md b/doc/scratch.md index 51d001c4bd..8145710eef 100644 --- a/doc/scratch.md +++ b/doc/scratch.md @@ -83,3 +83,143 @@ await (async () => { return await response.json(); })(); ``` + +## 2025-01-XX: Fix Sidebar Header Text Contrast Bug + +### Bug Description +When adjusting the lightness level of screen themes, sidebar header texts in the explorer become unreadable due to poor contrast between text and background colors. + +**Current Behavior:** +- Sidebar header text color is hardcoded to `#8f96a3` in `.window-sidebar-title` CSS class +- Sidebar background adapts to theme lightness via CSS variables +- At certain lightness values, the contrast between hardcoded text color and background becomes insufficient +- Text becomes difficult or impossible to read + +**Expected Behavior:** +- Sidebar header text should remain readable with adequate contrast across all theme lightness settings +- Should meet WCAG accessibility standards (minimum 4.5:1 contrast ratio for normal text) + +### Root Cause Analysis + +**Files Involved:** +1. `src/gui/src/css/style.css` (lines 1217-1234) + - `.window-sidebar-title` has hardcoded `color: #8f96a3;` + - Sidebar background uses: `hsla(var(--window-sidebar-hue), var(--window-sidebar-saturation), var(--window-sidebar-lightness), calc(0.5 + 0.5*var(--window-sidebar-alpha)))` + +2. `src/gui/src/services/ThemeService.js` + - Sets CSS variables: `--window-sidebar-hue`, `--window-sidebar-saturation`, `--window-sidebar-lightness`, `--window-sidebar-alpha` + - Sets `--window-sidebar-color` to `var(--primary-color)` which is either white or '#373e44' + - Does NOT set a variable for sidebar title text color + +3. `src/gui/src/css/style.css` (lines 99-103) + - CSS variables defined: `--window-sidebar-hue`, `--window-sidebar-saturation`, `--window-sidebar-lightness`, `--window-sidebar-alpha`, `--window-sidebar-color` + +### Proposed Solution + +#### Step 1: Create Contrast Calculation Utility +- **File**: `src/gui/src/services/ThemeService.js` (or create separate utility) +- **Action**: Add helper functions to: + - Convert HSL to RGB + - Calculate relative luminance (WCAG formula) + - Calculate contrast ratio between two colors + - Determine optimal text color (black or white) based on background color + - Consider sidebar background's effective color: `calc(0.5 + 0.5*alpha)` means final alpha is `0.5 + 0.5*alpha` + +#### Step 2: Calculate Sidebar Title Color Dynamically +- **File**: `src/gui/src/services/ThemeService.js` +- **Location**: In `reload_()` method +- **Action**: + - Calculate effective sidebar background color (considering alpha blend: `0.5 + 0.5*alpha`) + - Determine if background is light or dark + - Calculate appropriate text color that meets WCAG standards + - Set CSS variable `--window-sidebar-title-color` with calculated color + - Consider fallback to lighter/darker shades of the theme color if pure black/white doesn't work + +#### Step 3: Update CSS to Use Dynamic Color +- **File**: `src/gui/src/css/style.css` +- **Location**: `.window-sidebar-title` rule (line 1221) +- **Action**: + - Replace hardcoded `color: #8f96a3;` with `color: var(--window-sidebar-title-color, #8f96a3);` + - Use fallback color in case CSS variable is not set (for backwards compatibility) + +#### Step 4: Testing Plan +1. Test with various lightness values (0-100%) +2. Test with different hue and saturation values +3. Verify contrast ratio meets WCAG AA standards (4.5:1) for normal text +4. Test edge cases: + - Very light backgrounds (lig > 90%) + - Very dark backgrounds (lig < 10%) + - Medium backgrounds (lig ~ 50-60%) +5. Test with different alpha values +6. Visual regression testing - ensure text is readable at all settings + +#### Step 5: Implementation Details + +**Contrast Calculation Algorithm:** +```javascript +// Calculate relative luminance (WCAG) +function getLuminance(rgb) { + const [r, g, b] = rgb.map(val => { + val = val / 255; + return val <= 0.03928 ? val / 12.92 : Math.pow((val + 0.055) / 1.055, 2.4); + }); + return 0.2126 * r + 0.7152 * g + 0.0722 * b; +} + +// Calculate contrast ratio +function getContrastRatio(color1, color2) { + const l1 = getLuminance(color1); + const l2 = getLuminance(color2); + const lighter = Math.max(l1, l2); + const darker = Math.min(l1, l2); + return (lighter + 0.05) / (darker + 0.05); +} + +// Get optimal text color +function getOptimalTextColor(backgroundColor) { + // Calculate effective background color (considering alpha blend) + // Try black and white, choose one with better contrast + const blackContrast = getContrastRatio([0, 0, 0], backgroundColor); + const whiteContrast = getContrastRatio([255, 255, 255], backgroundColor); + + if (blackContrast >= 4.5 || whiteContrast < 4.5) { + return '#000000'; // or darker shade if needed + } else { + return '#ffffff'; // or lighter shade if needed + } +} +``` + +**ThemeService Integration:** +- In `reload_()` method, after setting other CSS variables: + 1. Calculate effective sidebar background RGB + 2. Determine optimal text color + 3. Set `--window-sidebar-title-color` CSS variable + +### Files to Modify + +1. ✅ `src/gui/src/services/ThemeService.js` + - Add contrast calculation utilities + - Calculate and set `--window-sidebar-title-color` in `reload_()` + +2. ✅ `src/gui/src/css/style.css` + - Update `.window-sidebar-title` to use CSS variable with fallback + +### Alternative Approaches Considered + +1. **CSS-only solution using `mix-blend-mode`**: + - Pros: No JS needed + - Cons: Browser compatibility issues, may affect other elements + +2. **CSS `color-contrast()` function**: + - Pros: Native CSS solution + - Cons: Limited browser support as of 2024 + +3. **Predefined color palettes**: + - Pros: Simple, predictable + - Cons: May not work for all lightness values, less flexible + +### Implementation Priority +- **High**: This is an accessibility issue affecting user experience +- **Impact**: Affects all users who customize theme lightness +- **Risk**: Low - isolated change to theme service and CSS diff --git a/src/gui/src/css/style.css b/src/gui/src/css/style.css index 4c7d1637e2..3d37b6be6a 100644 --- a/src/gui/src/css/style.css +++ b/src/gui/src/css/style.css @@ -1218,7 +1218,7 @@ span.header-sort-icon img { margin: 0; font-weight: bold; font-size: 13px; - color: #8f96a3; + color: var(--window-sidebar-title-color, #8f96a3); text-shadow: 1px 1px rgb(247 247 247 / 15%); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -1243,7 +1243,7 @@ span.header-sort-icon img { margin-top: 2px; padding: 4px; border-radius: 3px; - color: #444444; + color: var(--window-sidebar-item-color, #444444); font-size: 13px; cursor: pointer; transition: 0.15s background-color; diff --git a/src/gui/src/services/ThemeService.js b/src/gui/src/services/ThemeService.js index b49d41e684..4d2e04ee31 100644 --- a/src/gui/src/services/ThemeService.js +++ b/src/gui/src/services/ThemeService.js @@ -32,6 +32,114 @@ const default_values = { light_text: false, }; +/** + * Convert HSL color to RGB array [r, g, b] with values 0-255 + * @param {number} h - Hue (0-360) + * @param {number} s - Saturation (0-100) + * @param {number} l - Lightness (0-100) + * @returns {Array