Thank you! Last Recorded is perfect.
WinChannels has been pinned to my taskbar!!! where has this app been all this time! lol thanks again! being able to select the source for a live channel is the tool i've been missing.
Not sure why I'm seeing this
Version not yet detected. Connect to a server first.
Other than that, everything is working great!
Version 1.3.8 is now available. This one adds an error log and will create a bug report that you can post here. It also (properly) implements an API compatibility check for each configured server, and check for the existence of a new version.
v1.3.8 should provide a better compatibility check.
Thanks, but that just appears to be checking for the Channels DVR Server version, which will change with every prerelease version https://community.getchannels.com/t/dvr-pre-release-notes/28832/9999
There is no way to check the server API version (public documented or private undocumented) as far as I know. And the public documented API (/api/v1) hasn't changed for a long time Channels Support - Server API
I recently put in a request for an update to an API
Right. The mutations use the undocumented API. Those could change with any server version update, so I need to keep up with that. The delete (trash) command is unlikely to change, but as for the "mark as not recorded", it's not hard to imagine them creating a replacement protocol. Even so, they would not remove the existing command until all clients have been updated. Or so it says in the fine print I'm imagining 
Think it would be easier if you just verified (what you call) a mutation was working and report an error if not.
For example, with "mark as not recorded".
-
Verify the ProgramID exists in
/programsasrecordedbefore sending the command to delete it
"EP027201150081": "recorded-3385", -
Verify the ProgramID no longer exists in
/programsasrecordedafter sending the command to delete it. The pass scheduler could create a new entry in/programsfor aqueuedscheduled recording
"EP027201150081": "queued-1778066970-248",
Thanks for creating this incredible Windows app.
This is now my "go to" Channels client on Windows for my seven Channels DVR Servers.
Is there a list of keybinds for transport controls e.g. skip forward/back? Tried right/left arrow, did nothing. Also can the skip seconds be made configurable or is it the usual 30 sec forward, 7 sec back?
Good idea! Try v1.4.1 - keyboard navigation and playback shortcuts added. Also added configurable skip intervals.
Here is a synopsis of feature updates since the initial release. Please note, starting with version 1.3.6, the program checks for the existence of new releases. If you are using an older version, please visit the repository to get the latest version: Releases · jay3702/winchannels
v1.0.0 — Initial release: Recent Recordings, TV Shows, Movies, Library browsing, HLS playback with broadcast and SRT sidecar captions, multi-server support, and Settings.
v1.1.0 — Live TV view with channel browsing, source and Favorites filters, deduplication, and click-to-play. Source diagnostics matrix and "Stats for Nerds" player overlay (Shift+S). Windows ARM64 installer.
v1.1.8 — Hidden channels toggle in Live TV to suppress source-hidden and duplicate feeds. Linux x64 and ARM64 builds added.
v1.2.0 — Tailscale dual-address support with automatic LAN/Tailscale probe on startup. TV Shows redesigned to a two-level show → episode detail flow. Trash and Mark as Not Recorded actions in episode and recording detail panes. API version guard banner when the server version changes.
v1.2.2 — Sort toggle buttons (▲/▼) replace dropdowns across TV Shows and Movies.
v1.3.0 — Cross-library Search page with type filters (Any, Title, Summary, Series Name) and direct navigation to matching results. Recording file path shown in episode and movie detail panes. Sort direction overhaul with stacked ▲/▼ buttons and a Date Updated field option.
v1.3.1 — Cache-first page revisits for all views — pages render instantly from cache with a background refresh. Progressive list rendering for large libraries. Persisted sort selections. Resizable split-view panels for TV Shows and Library.
v1.3.4 / v1.3.5 — Last Recorded sort option added to TV shows list and set as the default.
v1.3.6 — Startup check for newer WinChannels releases; a banner links to the latest release on GitHub.
v1.3.7 — Repository-hosted API compatibility matrix with improved server version detection and clearer per-server compatibility status in Settings.
v1.3.8 — Local bug report composer with a persistent 48-hour client error log, server IP redaction, and auto-run connection test.
v1.4.0 — Auto-focus the first episode card when a TV show is selected, so keyboard navigation starts immediately.
v1.4.1 — Full keyboard D-pad navigation across sidebar, list, and grid zones. Configurable player keybindings and skip intervals in Settings.
Working great. No complaints 
Any possibility of adding a light-mode option? (Posted on Github, but maybe this is a better place to ask?) I find dark mode very hard on my eyes, and would like to be able to select light mode (or my system app mode, which is set to light) as an option.
Now that you mention it, I'm not a fan myself! Try version v1.5
Thanks! So much better!
Your quick fixes are awesome, and this is a truly great lightweight playback experience. When you get around to releasing another version, what do you think about adding support for double click on a show to quickly watch it instead of clicking on it and then clicking play? Totally minor detail lol.
Thanks!
Added to v1.6. I also fixed a bug that I found related to full screen playback.
You might be interested in the process I'm using for this project. I'm using VS Code and CoPilot. Claude Sonnet 4.6 does all the work; I tell it what I want, then test and direct. It's awesome! Here's an example of the process. This took about 40 minutes from my initial prompt to initiating the update to the repository. It took a lot longer to get this post to format the way I wanted, and I still can't get the 'thinking to myself" output to appear in context. That stuff is fascinating. For example, after I asked it to hide the menu when playing full screen, it said this:
The user wants the video player UI controls (header with buttons, commercial ad bar, progress indicators) to auto-hide after a few seconds of inactivity and reappear on mouse move/hover. This is a classic video player auto-hide controls pattern.
Let me look at the VideoPlayer component more carefully to understand the full structure.
Sometimes that process can go on for quite a while, and I can see that it has gone off on a tangent, made an incorrect assumption, or misunderstood my direction. At that point, you can add another prompt while it's working, and it will pick it up on the fly and change direction based on the new input.
I would defiantly be using this process if I was still working now, although, I'd be a lot more intimate with the code than I need to be for this project. It's still not at the point that you could completely replace programmers with AI, but it's definitely a productivity multiplier.
WinChannels Development Log — May 8, 2026
User
I have another request, and I found a minor bug. The request is to add double click as a shortcut to play. I think he is referring to the recent recordings list, since that's the only place where two clicks are required to get to play.
The bug is that the fullscreen view doesn't size properly if the aspect ratio of the active monitor is different than the aspect ratio of the content. For example, my current screen is a 32:9 widescreen. If I use the native fullscreen button in the playback, the video is displayed centered on the screen with black bars on the left and right sides. If I use our custom button, the video expands to the full width, with the bottom cropped. Incidentally, the same thing happens if I use the Windows resizing UI (snap layouts).
GitHub Copilot
Let me understand the two issues:
Double-click to play: Add a double-click shortcut on recording items in the Recent Recordings list — that's the only place requiring two clicks to play (click to select, then click the Play button in the detail pane).
Fullscreen aspect ratio bug: The custom fullscreen button and Windows snap/resize cause the video to expand to full width with the bottom cropped. The native browser fullscreen works correctly (black bars on sides). This is a CSS/sizing issue with the video element in a flex container.
Let me explore the codebase to understand the current implementation.
I read RecentRecordings.tsx, VideoPlayer.tsx, and VideoPlayer.css in parallel to get the full picture before touching anything.
What I found in VideoPlayer.css:
.video-element {
flex: 1;
width: 100%;
background: #000;
outline: none;
}
The .video-overlay is a display: flex; flex-direction: column container. When overlay.requestFullscreen() fires on a 32:9 monitor (~5120px wide), width: 100% makes the <video> element that same width. A flex child without min-height: 0 is allowed to grow beyond its allocated height based on its intrinsic aspect ratio — so a 16:9 video at 5120px wide computes a natural height of ~2880px, but the visible container is only ~1440px tall. The bottom gets clipped. The native fullscreen button doesn't have this problem because the browser applies its own containment. The fix is min-height: 0 (honor the flex allocation) and object-fit: contain (letterbox within it).
What I found in RecentRecordings.tsx:
<button
key={rec.id}
className={`rec-item ${selected?.id === rec.id ? 'rec-item--active' : ''}`}
onClick={() => selectRecording(rec)}
>
The playItem() function is already imported from the store and used by the detail pane's Play button with the same arguments. I just needed to wire it to onDoubleClick on this same button.
Fix 1 — Fullscreen aspect ratio (VideoPlayer.css)
.video-element {
flex: 1;
min-height: 0;
width: 100%;
object-fit: contain;
background: #000;
outline: none;
}
Fix 2 — Double-click to play (RecentRecordings.tsx)
<button
key={rec.id}
className={`rec-item ${selected?.id === rec.id ? 'rec-item--active' : ''}`}
onClick={() => selectRecording(rec)}
onDoubleClick={() => playItem(
rec.id,
recLabel(rec),
rec.path,
rec.commercials,
'',
rec.playback_time,
rec.show_id ? 'episode' : 'movie'
)}
>
User
That looks good. Can you also make the UI control elements (menu, commercial map, progress bar, etc) disappear after a few seconds? They should reappear on mouseover.
GitHub Copilot
The goal is to auto-hide the header bar and commercial timeline bar after a few seconds of inactivity, and restore them on mouse movement.
A few approaches to consider:
- Conditional rendering — unmount the elements when hidden. Rejected: causes layout shifts (the video element would resize to fill the space) and could lose DOM state (caption track selections, etc.).
-
CSS
visibility: hidden— hides visually but still occupies space. Doesn't help here since the header isflex-shrink: 0and would still push the video down. -
CSS
opacity: 0+pointer-events: none— visually hidden, click-through, no layout shift, animatable withtransition. This is the right choice.
Plan:
- Add
controlsVisiblestate, defaulting totrue - Add a
hideTimerRefto hold the timeout ID -
resetHideTimercallback: clears any pending timer, setscontrolsVisible(true), starts a new 3-second timeout that setscontrolsVisible(false) -
onMouseMove={resetHideTimer}on the overlay div - A
useEffectonnowPlayingKeyto start the timer when a new item begins playing, and clean up on unmount - CSS class
video-overlay--controls-hiddenapplied when!controlsVisible, which fades the header and ad bar out and setscursor: none
The skip toast and nerd stats panel are intentionally excluded — the toast is transient and auto-removes itself, and the stats panel should remain readable during debugging without needing to move the mouse.
resetHideTimer is a stable useCallback (no dependencies that change) so it can be safely listed as a useEffect dependency without causing re-registration loops.
Changes — VideoPlayer.tsx
New state and ref (added alongside isOverlayFullscreen):
const [isOverlayFullscreen, setIsOverlayFullscreen] = useState(false);
const [controlsVisible, setControlsVisible] = useState(true);
const hideTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
New callback and effect (added before the existing skipBy):
// Auto-hide controls after inactivity; reset on mouse movement
const resetHideTimer = useCallback(() => {
if (hideTimerRef.current !== null) window.clearTimeout(hideTimerRef.current);
setControlsVisible(true);
hideTimerRef.current = window.setTimeout(() => setControlsVisible(false), 3000);
}, []);
useEffect(() => {
resetHideTimer();
return () => {
if (hideTimerRef.current !== null) window.clearTimeout(hideTimerRef.current);
};
}, [nowPlayingKey, resetHideTimer]);
Overlay div — class and mouse handler:
<div
className={`video-overlay${controlsVisible ? '' : ' video-overlay--controls-hidden'}`}
ref={overlayRef}
tabIndex={0}
onMouseMove={resetHideTimer}
>
Changes — VideoPlayer.css
Transitions on the two affected elements:
.video-header {
/* ...existing styles... */
transition: opacity 0.3s ease;
}
.video-ad-bar {
/* ...existing styles... */
transition: opacity 0.3s ease;
}
New rules for the hidden state:
.video-overlay--controls-hidden {
cursor: none;
}
.video-overlay--controls-hidden .video-header,
.video-overlay--controls-hidden .video-ad-bar {
opacity: 0;
pointer-events: none;
}
User
Looks good. Please increment the version, push and tag.
GitHub Copilot
New features added (double-click to play, auto-hide controls) plus the fullscreen fix — minor bump → v1.6.0. After confirmation:
- Bumped
versionin package.json, tauri.conf.json, and Cargo.toml - Updated ENGINEERING_JOURNAL.md
git add -A && git commit -m "v1.6.0: double-click to play, auto-hide player controls, fullscreen aspect ratio fix"git push origin maingit tag v1.6.0 && git push origin v1.6.0
I may be missing something obvious here, but how do you sort a TV Show's episodes by Season, then Episode? So this example would sort as S1E1, S1E2, S1E3, S1E4, S1E5, S1E6
None of the available sort options work.
This one just happens to work because it was recorded in episode order.
I added season and episode as well as first aired. Also added release date to movies. V1.7 - it may take a few minutes to finish building...


