mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
fix(xtream): improve sync overlay contrast in both themes (#1546)
This commit is contained in:
1 parent
e40f31db97
commit
002faafbd7
4 files changed
+106
-19
No files matched your search
@@ -0,0 +1,6 @@
|
||||
---
|
||||
type: fix
|
||||
area: xtream
|
||||
---
|
||||
|
||||
The Xtream sync panel now keeps its status text, labels and Stop sync button clearly readable in both light and dark themes.
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
import { applyTheme, expectTextContrast } from './theme-contrast';
|
||||
|
||||
import {
|
||||
addStalkerPortal,
|
||||
@@ -20,6 +21,55 @@ import {
|
||||
} from './electron-test-fixtures';
|
||||
|
||||
test.describe('Electron Provider Smoke Tests', () => {
|
||||
test('@xtream @theme @electron keeps sync overlay text readable in both themes', async ({
|
||||
dataDir,
|
||||
request,
|
||||
}) => {
|
||||
await resetMockServers(request, ['xtream']);
|
||||
const app = await launchElectronApp(dataDir);
|
||||
try {
|
||||
// Hold the cache read so the real local-library overlay stays
|
||||
// mounted while its theme and Material interaction states change.
|
||||
await app.electronApp.evaluate(({ ipcMain }) => {
|
||||
ipcMain.removeHandler('DB_GET_CATEGORIES');
|
||||
ipcMain.handle(
|
||||
'DB_GET_CATEGORIES',
|
||||
() => new Promise(() => {
|
||||
// Intentionally pending until this isolated app closes.
|
||||
})
|
||||
);
|
||||
});
|
||||
await addXtreamPortal(app.mainWindow);
|
||||
const overlay = app.mainWindow.locator(
|
||||
'app-workspace-shell-import-overlay'
|
||||
);
|
||||
await expect(overlay).toContainText('Loading the saved catalog');
|
||||
const action = overlay.getByRole('button', { name: 'Stop sync' });
|
||||
for (const theme of ['light', 'dark', 'light'] as const) {
|
||||
await applyTheme(app.mainWindow, theme);
|
||||
for (const selector of [
|
||||
'h3',
|
||||
'.workspace-loading-overlay__badge',
|
||||
'.workspace-loading-overlay__phase',
|
||||
'.workspace-loading-overlay__detail',
|
||||
]) {
|
||||
await expectTextContrast(overlay.locator(selector));
|
||||
}
|
||||
// Leave headroom for Material's translucent hover/focus layer.
|
||||
await expectTextContrast(action, 6);
|
||||
await action.hover();
|
||||
await expectTextContrast(action);
|
||||
await action.focus();
|
||||
await expectTextContrast(action);
|
||||
await app.mainWindow.screenshot({
|
||||
path: test.info().outputPath(`sync-overlay-${theme}.png`),
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await closeElectronApp(app);
|
||||
}
|
||||
});
|
||||
|
||||
test('@xtream @electron loads Xtream content through the Electron IPC path', async ({
|
||||
dataDir,
|
||||
request,
|
||||
|
||||
@@ -325,6 +325,17 @@ remain local when the meaning is explicit.
|
||||
- Use a solid or near-solid backing surface
|
||||
- Do not let it overlap or cover player controls
|
||||
|
||||
## Workspace Xtream Sync Overlay
|
||||
|
||||
The import/refresh card pairs a near-opaque `--app-widget-bg` surface with
|
||||
app-owned text colors in both themes. Blur belongs to the backdrop; card text
|
||||
must not depend on an unprovided Material system surface token. Phase text uses
|
||||
the primary foreground, and explanatory/progress copy uses a readable blend of
|
||||
primary text and the widget surface instead of the decorative muted token.
|
||||
Local and remote badges, and the outlined cancel button, resolve their text,
|
||||
surfaces and interaction colors together. Electron provider E2E coverage holds
|
||||
a cache read open and checks text contrast across live theme changes.
|
||||
|
||||
## Progress Bars
|
||||
|
||||
Channel preview progress and EPG current-program progress should stay visually aligned.
|
||||
|
||||
+39
-19
@@ -1,3 +1,5 @@
|
||||
@use '@angular/material' as mat;
|
||||
|
||||
:host {
|
||||
display: contents;
|
||||
}
|
||||
@@ -21,19 +23,26 @@
|
||||
}
|
||||
|
||||
.workspace-loading-overlay__card {
|
||||
--sync-secondary: color-mix(
|
||||
in srgb,
|
||||
var(--app-on-surface) 78%,
|
||||
var(--app-widget-bg)
|
||||
);
|
||||
--sync-accent: color-mix(
|
||||
in srgb,
|
||||
var(--app-selection-color) 60%,
|
||||
var(--app-on-surface)
|
||||
);
|
||||
|
||||
width: min(440px, 100%);
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
padding: 24px 24px 20px;
|
||||
border-radius: 24px;
|
||||
border: 1px solid var(--app-separator, rgba(255, 255, 255, 0.12));
|
||||
background:
|
||||
linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.06),
|
||||
rgba(255, 255, 255, 0)
|
||||
),
|
||||
var(--mat-sys-surface-container-high);
|
||||
border: 1px solid var(--app-separator);
|
||||
// Keep a bounded glass tint without letting the scrim own text contrast.
|
||||
background: color-mix(in srgb, var(--app-widget-bg) 96%, transparent);
|
||||
color: var(--app-on-surface);
|
||||
box-shadow:
|
||||
0 24px 64px rgba(0, 0, 0, 0.32),
|
||||
0 1px 0 rgba(255, 255, 255, 0.05) inset;
|
||||
@@ -45,7 +54,7 @@
|
||||
font-size: 1.55rem;
|
||||
font-weight: 650;
|
||||
letter-spacing: -0.03em;
|
||||
color: var(--app-heading-color, var(--mat-sys-on-surface));
|
||||
color: var(--app-heading-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,9 +70,9 @@
|
||||
justify-content: center;
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(120, 220, 255, 0.24);
|
||||
background: rgba(120, 220, 255, 0.08);
|
||||
color: rgba(164, 233, 255, 1);
|
||||
border: 1px solid var(--app-separator);
|
||||
background: var(--app-hover-overlay);
|
||||
color: var(--sync-secondary);
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.12em;
|
||||
@@ -71,9 +80,9 @@
|
||||
}
|
||||
|
||||
.workspace-loading-overlay__badge--remote {
|
||||
border-color: rgba(105, 195, 255, 0.34);
|
||||
background: rgba(83, 158, 255, 0.12);
|
||||
color: rgba(202, 230, 255, 1);
|
||||
border-color: var(--app-selection-border);
|
||||
background: var(--app-selection-surface);
|
||||
color: var(--sync-accent);
|
||||
}
|
||||
|
||||
.workspace-loading-overlay__phase,
|
||||
@@ -84,14 +93,14 @@
|
||||
|
||||
.workspace-loading-overlay__phase {
|
||||
font-size: 1rem;
|
||||
font-weight: 560;
|
||||
color: var(--app-body-color, var(--mat-sys-on-surface));
|
||||
font-weight: 600;
|
||||
color: var(--app-on-surface);
|
||||
}
|
||||
|
||||
.workspace-loading-overlay__detail {
|
||||
max-width: 32ch;
|
||||
justify-self: center;
|
||||
color: var(--app-muted-color, var(--mat-sys-on-surface-variant));
|
||||
color: var(--sync-secondary);
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
@@ -100,11 +109,22 @@
|
||||
justify-self: center;
|
||||
line-height: 1.45;
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: var(--app-muted-color, var(--mat-sys-on-surface-variant));
|
||||
color: var(--sync-secondary);
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.workspace-loading-overlay__action {
|
||||
@include mat.button-overrides(
|
||||
(
|
||||
outlined-label-text-color: var(--sync-accent),
|
||||
outlined-label-text-weight: 600,
|
||||
outlined-outline-color: var(--sync-secondary),
|
||||
outlined-state-layer-color: var(--app-on-surface),
|
||||
outlined-disabled-label-text-color: var(--sync-secondary),
|
||||
outlined-disabled-outline-color: var(--app-separator),
|
||||
)
|
||||
);
|
||||
|
||||
justify-self: center;
|
||||
min-width: 180px;
|
||||
border-radius: 999px;
|
||||
|
||||
Reference in new issue
Block a user