* fix(import): consistent add-source forms with masked passwords and URL errors
- Mask the Xtream password in add and edit (and the Stalker one in edit)
behind a shared PasswordVisibilityToggleDirective: one translated
"Show password" label, state in aria-pressed, type="button".
- Give the Xtream server URL its own mat-error and a neutral hint instead
of the EPG file error; give the M3U URL a mat-error.
- Use "Playlist title" in every add form, "MAC address" casing, a single
ellipsis in "Validating portal…" and one "Add playlist" submit label;
translate the method radiogroup's aria-label.
- Show Stalker refusals inline under the portal URL (role="status", like
the Xtream connection test), translated in the template and cleared by
edits; translate the snackbars for outcomes that close the dialog.
- Translate new strings into all locales; reuse the identical Stalker URL
error translations; fix MAC casing and ellipses; drop unused keys.
- Unit specs per form, edit-dialog spec, new add-source-forms web E2E;
update E2E locators; UI guidelines Forms section; Stalker contract.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(import): mask the password again when an add form is cleared
Clear erased the password but left the visibility toggle on, so the next
password typed in the Xtream or Stalker form showed in plain text.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* chore(deps): upgrade Angular to 22.1 and Nx to 23.2
* fix(deps): complete Angular migrations after rebasing on master
* fix(ci): use the Node pin for Windows runtime refresh
* docs(deps): synchronize the workspace-shell Node requirements
Adds an "Auto-detect" method to the Add playlist dialog: paste the message a
provider sent — links, Xtream credentials, a MAC address with device identity
— and a deterministic parser recognizes the source(s) and prefills the
matching import form.
- detectProviderImportCandidates (libs/shared/interfaces) extracts URLs, MAC
addresses and labeled fields, classifies each finding as Xtream, Stalker or
an M3U link/body, and returns ranked candidates. Pure and synchronous.
- Built against a corpus of 19 real reseller handouts kept verbatim in the
spec: Unicode "font" labels, arrow/dingbat separators, separator-less hex
serials, dual device IDs, multi-MAC lists, bare three-line handouts, and a
guard so a parental PIN is never read as the account password.
- Detection only proposes: the target form's own validation and behavioral
probes remain the sole path into the store, and no pasted text leaves the
app. Passwords are masked on candidate cards, including query and HTTP
Basic userinfo forms.
- Covered by parser, component and dialog unit tests plus two web E2E specs
for the paste → pick → prefilled form workflow; i18n for all 19 languages.
The redesign rollup in this branch replaced the Add Playlist dialog's
2-level type × subtype tabs with a single flat 5-card radiogroup, and
replaced the Settings theme list with a compact segmented control whose
options are just "Light"/"Dark"/"System" (no "theme" suffix). E2E tests
that pinned to the old roles/labels failed in CI:
- basic / xtream / stalker / self-hosted: getByRole('tab', ...) on
"Add via file upload" / "Xtream" / "Stalker" — there are no tabs in
the new dialog. Switched to getByRole('radio', { name: /M3U file/i })
and friends, matched against the new radio labels.
- settings: getByRole('radio', { name: 'System theme' }) — the new
picker uses just "System". Scoped to the [data-test-id="select-theme"]
radiogroup so it doesn't collide with the identically-labelled
cover-size options below.
The Electron `clickDialogSegmentedOption` helper grew a radio-role lookup
as its primary path and keeps the old tab/button/legacy-selector
fallbacks so a future redesign won't break every fixture again. The
"M3U" parent category becomes a no-op (the new picker has no standalone
M3U tile — callers always specialise to M3U URL/file/text immediately
after, which is what we want anyway).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
mat-button-toggle elements inside a group render their internal buttons
with role="radio", not role="button", so getByRole('button') selectors
fail. Switch to attribute selectors targeting the value attribute instead.
https://claude.ai/code/session_01VU6ZZTG7YrhKhKBQvBfmpp
- Implemented tests for importing M3U playlists via native dialog.
- Added smoke tests for loading Xtream and Stalker content through IPC.
- Created tests to verify persistence of remote control settings across app restarts.
- Updated smoke tests to check for main window properties and workspace content rendering.
refactor(electron-backend): enhance store service and database path handling
- Modified store service to use a dynamic configuration directory based on environment.
- Refactored database connection to utilize new path utility functions for better path management.
fix(e2e): improve test selectors and structure for better reliability
- Updated test selectors in web-e2e tests to use role-based queries for better accessibility.
- Refactored settings tests to reduce redundancy and improve clarity.
chore(e2e): update TypeScript configuration for better inclusion of test files
- Adjusted tsconfig.json to ensure proper inclusion of e2e test files.
Entire-Checkpoint: bb9a8e2e351e