feat(clients/windows): game library page + session window placement + help polish
apple / swift (push) Successful in 1m10s
android / android (push) Successful in 4m56s
arch / build-publish (push) Successful in 5m56s
audit / bun-audit (push) Successful in 13s
audit / cargo-audit (push) Successful in 1m34s
ci / web (push) Successful in 1m11s
windows-host / package (push) Successful in 7m57s
ci / docs-site (push) Successful in 1m27s
release / apple (push) Successful in 8m39s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m26s
ci / bench (push) Successful in 5m0s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m16s
apple / screenshots (push) Successful in 5m35s
ci / rust (push) Successful in 10m32s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m47s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m36s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
deb / build-publish (push) Successful in 6m38s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m39s
flatpak / build-publish (push) Successful in 5m32s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m0s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m33s
docker / deploy-docs (push) Successful in 18s
apple / swift (push) Successful in 1m10s
android / android (push) Successful in 4m56s
arch / build-publish (push) Successful in 5m56s
audit / bun-audit (push) Successful in 13s
audit / cargo-audit (push) Successful in 1m34s
ci / web (push) Successful in 1m11s
windows-host / package (push) Successful in 7m57s
ci / docs-site (push) Successful in 1m27s
release / apple (push) Successful in 8m39s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m26s
ci / bench (push) Successful in 5m0s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m16s
apple / screenshots (push) Successful in 5m35s
ci / rust (push) Successful in 10m32s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m47s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m36s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
deb / build-publish (push) Successful in 6m38s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m39s
flatpak / build-publish (push) Successful in 5m32s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m0s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m33s
docker / deploy-docs (push) Successful in 18s
UX polish batch 2 (plan workstreams D/E5/E6): - D: a mouse/keyboard game library page over pf-client-core::library (the GTK ui_library.rs counterpart): responsive 2-6 column poster grid (2:3 portraits, store badge, monogram placeholder while art streams in), loading / error+retry / empty / grid states, tap-to-play via a normal spawn carrying --launch id. Poster bytes land in a disk cache (%LOCALAPPDATA%\punktfunk\art-cache) so the Image widget loads file:/// URIs (reactor has no from-bytes source) and revisits render instantly. Reached from a paired host's "Browse library..." menu item behind the new "Show game library (experimental)" Settings toggle (the shared library_enabled field, Apple/GTK parity). A Shared::library_gen generation guard keeps a superseded fetch from publishing (speed-test pattern). - E5: the session window opens at the shell's own top-left (--window-pos, new SessionOpts::window_pos) instead of centered on the primary display - streams land on the monitor the shell is on, and the hide/restore handoff reads as one window changing content. Fullscreen follows that display. - E6: the Help shortcuts add Alt+Enter and the controller escape chord (LB+RB+Start+Back, hold to disconnect). Also: rustfmt normalization of the merged probe helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ use windows_reactor::*;
|
||||
|
||||
/// Overflow-menu item labels — `on_item_clicked` reports the clicked item by its text.
|
||||
const MENU_CONNECT: &str = "Connect";
|
||||
const MENU_LIBRARY: &str = "Browse library\u{2026}";
|
||||
const MENU_CONSOLE: &str = "Open console UI";
|
||||
const MENU_SPEED: &str = "Test network speed\u{2026}";
|
||||
const MENU_WAKE: &str = "Wake host";
|
||||
@@ -186,22 +187,6 @@ fn status_row(online: Option<bool>, badge: &str, kind: Pill) -> Element {
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Lay tiles into a `cols`-wide grid of equal-width star columns (rows share the height of
|
||||
/// their tallest tile, so a grid row always lines up).
|
||||
fn tile_grid(tiles: Vec<Element>, cols: usize) -> Element {
|
||||
let rows = tiles.len().div_ceil(cols);
|
||||
let mut children = Vec::with_capacity(tiles.len());
|
||||
for (i, t) in tiles.into_iter().enumerate() {
|
||||
children.push(t.grid_row((i / cols) as i32).grid_column((i % cols) as i32));
|
||||
}
|
||||
grid(children)
|
||||
.columns(vec![GridLength::Star(1.0); cols])
|
||||
.rows(vec![GridLength::Auto; rows])
|
||||
.column_spacing(TILE_GAP)
|
||||
.row_spacing(TILE_GAP)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// The in-tile rename editor (ContentDialog can't hold a text field): name box + save/cancel.
|
||||
/// No tap-to-connect while editing — a click into the box would bubble `Tapped` to the region.
|
||||
fn rename_editor(
|
||||
@@ -269,6 +254,8 @@ pub(crate) fn hosts_page(props: &HostsProps, cx: &mut RenderCx) -> Element {
|
||||
set: props.set_hover.clone(),
|
||||
};
|
||||
let known = KnownHosts::load();
|
||||
// The experimental library gate ("Show game library" in Settings) — GTK/Apple parity.
|
||||
let library_enabled = ctx.settings.lock().unwrap().library_enabled;
|
||||
|
||||
// Responsive column count from the live window width (re-renders on resize): as many
|
||||
// TILE_MIN_WIDTH columns as fit the page's content width, at least one.
|
||||
@@ -445,8 +432,13 @@ pub(crate) fn hosts_page(props: &HostsProps, cx: &mut RenderCx) -> Element {
|
||||
.automation_name("More options")
|
||||
.menu_flyout({
|
||||
let mut items = vec![menu_item(MENU_CONNECT)];
|
||||
// The gamepad library — paired hosts only (the mgmt API needs the
|
||||
// paired identity) and only where the session ships the console UI.
|
||||
// The library surfaces — mouse/KB page and the gamepad console UI —
|
||||
// for paired hosts only (the mgmt API needs the paired identity);
|
||||
// the page additionally sits behind the experimental toggle, the
|
||||
// console UI behind the x64-only skia build.
|
||||
if library_enabled && k.paired {
|
||||
items.push(menu_item(MENU_LIBRARY));
|
||||
}
|
||||
if CONSOLE_UI_AVAILABLE && k.paired {
|
||||
items.push(menu_item(MENU_CONSOLE));
|
||||
}
|
||||
@@ -464,6 +456,11 @@ pub(crate) fn hosts_page(props: &HostsProps, cx: &mut RenderCx) -> Element {
|
||||
MENU_CONNECT => {
|
||||
initiate(&svc.ctx, target.clone(), &svc.set_screen, &svc.set_status)
|
||||
}
|
||||
MENU_LIBRARY => {
|
||||
*svc.ctx.shared.target.lock().unwrap() = target.clone();
|
||||
super::library::start_fetch(&svc.ctx, &svc.set_library);
|
||||
svc.set_screen.call(Screen::Library);
|
||||
}
|
||||
MENU_CONSOLE => {
|
||||
open_console(&svc.ctx, target.clone(), &svc.set_screen, &svc.set_status)
|
||||
}
|
||||
@@ -508,7 +505,7 @@ pub(crate) fn hosts_page(props: &HostsProps, cx: &mut RenderCx) -> Element {
|
||||
})),
|
||||
));
|
||||
}
|
||||
body.push(tile_grid(tiles, cols));
|
||||
body.push(tile_grid(tiles, cols, TILE_GAP));
|
||||
}
|
||||
|
||||
// Discovered hosts not already saved above.
|
||||
@@ -560,7 +557,7 @@ pub(crate) fn hosts_page(props: &HostsProps, cx: &mut RenderCx) -> Element {
|
||||
Some(Box::new(move || initiate(&ctx2, target.clone(), &ss, &st))),
|
||||
));
|
||||
}
|
||||
body.push(tile_grid(tiles, cols));
|
||||
body.push(tile_grid(tiles, cols, TILE_GAP));
|
||||
}
|
||||
|
||||
// Forget confirmation (modal; shown while `forget` holds a pending host). Confirmed first,
|
||||
|
||||
Reference in New Issue
Block a user