mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 01:56:16 -08:00
* feat(ui): add custom title bar window controls for Windows and Linux Hide the native title bar on win32/linux (titleBarStyle: 'hidden', frame untouched so native resize borders and snapping keep working) and render minimize / maximize-restore / close buttons in the renderer, mirroring the existing macOS traffic-light setup. - New WINDOW:* IPC contract (minimize, toggle-maximize, close, get-state) handled in window.events.ts, resolved from the sender WebContents; close goes through win.close() so window-bounds persistence still runs. - WINDOW:STATE_CHANGED pushed on maximize/unmaximize/fullscreen so the maximize/restore glyph stays correct for OS-triggered changes; controls hide while fullscreen. - WindowControlsComponent mounts once in app-root as a manual popover so it stays in the browser top layer above CDK overlays (dialogs, multi-EPG) - same behavior as macOS traffic lights. - Theme-aware via CSS vars (--app-on-surface, --app-hover-overlay); Windows-red close hover. Drag regions get right padding through a body-level frameless-platform class. - Gated by RuntimeCapabilitiesService.usesCustomWindowControls; PWA and macOS never mount the controls. Includes unit specs for the component and IPC handlers, an Electron E2E suite (window-controls.e2e.ts), and a window-chrome section in docs/architecture/workspace-shell.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(linux): upgrade Electron to 41 for frameless window decorations on Wayland With the native title bar hidden, Linux windows lost the WM-drawn shadow and rounded corners. Electron draws client-side decorations only on native Wayland, and frameless-window CSD (GTK drop shadow + extended resize boundaries) landed in Electron 41 - before that, frameless windows render as plain rectangles. - electron ^39.8.5 -> ^41.7.2 (Wayland auto-detected since 38.2; X11 sessions remain undecorated, matching other frameless Electron apps; Windows keeps its DWM shadow and rounded corners). - better-sqlite3 pinned to exactly 12.9.0: the last release shipping prebuilt binaries for both Node 20 (ABI 115, Jest) and Electron 41 (ABI 145, runtime). 12.10.0 dropped the Node 20 prebuilds, forcing a from-source build that fails without a C++ toolchain. - pnpm override node-abi 3.85.0 -> 3.92.0 so electron-builder install-app-deps can map Electron 41 to ABI 145. Reviewed Electron 40/41 breaking changes: only the renderer clipboard deprecation, which this app does not use. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(e2e): address review feedback and window-managerless Linux CI - Skip the three window-manager-dependent E2E assertions (maximize toggle, main-process state sync, minimize) on Linux CI: GitHub's ubuntu runners drive Electron under xvfb without a window manager, so maximize/minimize state never materializes there. Windows CI and local Linux/macOS runs keep the coverage. - WINDOW:TOGGLE_MAXIMIZE now returns the requested state instead of re-reading isMaximized() right after the call, which races on Linux window managers where maximize()/unmaximize() complete asynchronously; the WINDOW:STATE_CHANGED push stays authoritative. - Skip attaching window-state push listeners on macOS, where the custom controls never mount and the IPC traffic had no subscriber. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ui): gate custom window controls on the full bridge surface Include getWindowState and onWindowStateChange in the usesCustomWindowControls capability check — the controls rely on both for initial state and for keeping the maximize/restore glyph in sync with OS-triggered changes, so a partial bridge should not mount them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
85 lines
3.8 KiB
TypeScript
85 lines
3.8 KiB
TypeScript
// EPG related commands
|
|
export const EPG_FETCH = 'EPG:FETCH';
|
|
export const EPG_FETCH_DONE = 'EPG:FETCH_DONE';
|
|
export const EPG_ERROR = 'EPG:ERROR';
|
|
export const EPG_GET_CHANNELS = 'EPG:GET_CHANNELS';
|
|
export const EPG_GET_CHANNELS_DONE = 'EPG:GET_CHANNELS_DONE';
|
|
export const EPG_GET_CHANNELS_BY_RANGE = 'EPG:EPG_GET_CHANNELS_BY_RANGE';
|
|
export const EPG_GET_CHANNELS_BY_RANGE_RESPONSE =
|
|
'EPG:EPG_GET_CHANNELS_BY_RANGE_RESPONSE';
|
|
export const EPG_FORCE_FETCH = 'EPG:EPG_FORCE_FETCH';
|
|
|
|
// Playlist related commands
|
|
export const PLAYLIST_PARSE_BY_URL = 'PLAYLIST:PARSE_PLAYLIST_BY_URL';
|
|
export const PLAYLIST_UPDATE = 'PLAYLIST:UPDATE';
|
|
export const PLAYLIST_REFRESH = 'PLAYLIST:REFRESH';
|
|
export const PLAYLIST_REFRESH_EVENT = 'PLAYLIST:REFRESH_EVENT';
|
|
export const PLAYLIST_CANCEL_REFRESH = 'PLAYLIST:CANCEL_REFRESH';
|
|
|
|
// General
|
|
export const ERROR = 'ERROR';
|
|
export const OPEN_FILE = 'OPEN_FILE';
|
|
|
|
// Views
|
|
export const VIEW_SETTINGS = 'VIEW:SETTINGS';
|
|
export const VIEW_ADD_PLAYLIST = 'VIEW:PLAYLISTS';
|
|
|
|
// Auto-update
|
|
export const AUTO_UPDATE_PLAYLISTS = 'AUTO_UPDATE';
|
|
export const AUTO_UPDATE_PLAYLISTS_RESPONSE = 'AUTO_UPDATE_RESPONSE';
|
|
|
|
// Experimental
|
|
export const OPEN_MPV_PLAYER = 'OPEN_MPV_PLAYER';
|
|
export const SET_MPV_PLAYER_PATH = 'SET_MPV_PLAYER_PATH';
|
|
export const SET_MPV_REUSE_INSTANCE = 'SET_MPV_REUSE_INSTANCE';
|
|
export const OPEN_VLC_PLAYER = 'OPEN_VLC_PLAYER';
|
|
export const SET_VLC_PLAYER_PATH = 'SET_VLC_PLAYER_PATH';
|
|
export const SET_VLC_REUSE_INSTANCE = 'SET_VLC_REUSE_INSTANCE';
|
|
export const CLOSE_EXTERNAL_PLAYER_SESSION = 'CLOSE_EXTERNAL_PLAYER_SESSION';
|
|
export const EXTERNAL_PLAYER_SESSION_UPDATE = 'EXTERNAL_PLAYER_SESSION_UPDATE';
|
|
export const EMBEDDED_MPV_SUPPORT = 'EMBEDDED_MPV_SUPPORT';
|
|
export const EMBEDDED_MPV_CREATE_SESSION = 'EMBEDDED_MPV_CREATE_SESSION';
|
|
export const EMBEDDED_MPV_LOAD_PLAYBACK = 'EMBEDDED_MPV_LOAD_PLAYBACK';
|
|
export const EMBEDDED_MPV_SET_BOUNDS = 'EMBEDDED_MPV_SET_BOUNDS';
|
|
export const EMBEDDED_MPV_SET_PAUSED = 'EMBEDDED_MPV_SET_PAUSED';
|
|
export const EMBEDDED_MPV_SEEK = 'EMBEDDED_MPV_SEEK';
|
|
export const EMBEDDED_MPV_SET_VOLUME = 'EMBEDDED_MPV_SET_VOLUME';
|
|
export const EMBEDDED_MPV_SET_AUDIO_TRACK = 'EMBEDDED_MPV_SET_AUDIO_TRACK';
|
|
export const EMBEDDED_MPV_SET_SUBTITLE_TRACK =
|
|
'EMBEDDED_MPV_SET_SUBTITLE_TRACK';
|
|
export const EMBEDDED_MPV_SET_SPEED = 'EMBEDDED_MPV_SET_SPEED';
|
|
export const EMBEDDED_MPV_SET_ASPECT = 'EMBEDDED_MPV_SET_ASPECT';
|
|
export const EMBEDDED_MPV_START_RECORDING = 'EMBEDDED_MPV_START_RECORDING';
|
|
export const EMBEDDED_MPV_STOP_RECORDING = 'EMBEDDED_MPV_STOP_RECORDING';
|
|
export const EMBEDDED_MPV_GET_DEFAULT_RECORDING_FOLDER =
|
|
'EMBEDDED_MPV_GET_DEFAULT_RECORDING_FOLDER';
|
|
export const EMBEDDED_MPV_SELECT_RECORDING_FOLDER =
|
|
'EMBEDDED_MPV_SELECT_RECORDING_FOLDER';
|
|
export const EMBEDDED_MPV_DISPOSE_SESSION = 'EMBEDDED_MPV_DISPOSE_SESSION';
|
|
export const EMBEDDED_MPV_SESSION_UPDATE = 'EMBEDDED_MPV_SESSION_UPDATE';
|
|
export const EMBEDDED_MPV_PREPARE = 'EMBEDDED_MPV_PREPARE';
|
|
|
|
// Xtream
|
|
export const XTREAM_REQUEST = 'XTREAM_REQUEST';
|
|
export const XTREAM_RESPONSE = 'XTREAM_RESPONSE';
|
|
export const XTREAM_CANCEL_SESSION = 'XTREAM_CANCEL_SESSION';
|
|
|
|
// Stalker
|
|
export const STALKER_REQUEST = 'STALKER_REQUEST';
|
|
export const STALKER_RESPONSE = 'STALKER_RESPONSE';
|
|
export const PORTAL_DEBUG_EVENT = 'PORTAL_DEBUG_EVENT';
|
|
|
|
// Settings
|
|
export const SETTINGS_UPDATE = 'SETTINGS_UPDATE';
|
|
export const DELETE_ALL_PLAYLISTS = 'DELETE_ALL_PLAYLISTS';
|
|
|
|
// Remote Control
|
|
export const REMOTE_CONTROL_CHANGE_CHANNEL = 'REMOTE_CONTROL_CHANGE_CHANNEL';
|
|
|
|
// Window controls (custom title bar on Windows/Linux)
|
|
export const WINDOW_MINIMIZE = 'WINDOW:MINIMIZE';
|
|
export const WINDOW_TOGGLE_MAXIMIZE = 'WINDOW:TOGGLE_MAXIMIZE';
|
|
export const WINDOW_CLOSE = 'WINDOW:CLOSE';
|
|
export const WINDOW_GET_STATE = 'WINDOW:GET_STATE';
|
|
export const WINDOW_STATE_CHANGED = 'WINDOW:STATE_CHANGED';
|