Add GUI exit button and F11/Alt+Enter fullscreen toggle

This commit is contained in:
LeoVasanko committed 2026-09-24 04:52:33 +00:00
1 parent 9b12e53039
commit d01bf1d88f
3 files changed
+58 -1

No files matched your search

+43 -1
View File
@@ -1,5 +1,8 @@
<template> <template>
<header class="header" :class="[`header-${position}`]"> <header class="header" :class="[`header-${position}`, { 'header--gui': isDesktopApp }]">
<button v-if="isDesktopApp" class="app-exit-btn" title="Exit MediaHive" @click="exitApp">
✕
</button>
<div class="header-left"> <div class="header-left">
<RouterLink to="/" class="header-logo-link" aria-label="Go to front page"> <RouterLink to="/" class="header-logo-link" aria-label="Go to front page">
<img :src="logoUrl" alt="MediaHive" class="header-logo" /> <img :src="logoUrl" alt="MediaHive" class="header-logo" />
@@ -447,6 +450,11 @@ function _onPywebviewReady() {
window.addEventListener("pywebviewready", _onPywebviewReady, { once: true }) window.addEventListener("pywebviewready", _onPywebviewReady, { once: true })
onUnmounted(() => window.removeEventListener("pywebviewready", _onPywebviewReady)) onUnmounted(() => window.removeEventListener("pywebviewready", _onPywebviewReady))
function exitApp() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
void (window as any).pywebview?.api?.exit_app()
}
const showSettings = useSettingsOpen() const showSettings = useSettingsOpen()
const roots = computed(() => props.roots) const roots = computed(() => props.roots)
@@ -718,6 +726,17 @@ function focusSearchInput() {
} }
function handleKeydown(e: KeyboardEvent) { function handleKeydown(e: KeyboardEvent) {
// Fullscreen toggle works even while typing (Alt+Enter / F11 are never text input).
if (
isDesktopApp.value &&
(e.key === "F11" || (e.key === "Enter" && e.altKey && !e.ctrlKey && !e.metaKey))
) {
e.preventDefault()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
void (window as any).pywebview?.api?.toggle_fullscreen()
return
}
const target = e.target as HTMLElement | null const target = e.target as HTMLElement | null
const isTypingTarget = Boolean( const isTypingTarget = Boolean(
target && target &&
@@ -749,6 +768,29 @@ onUnmounted(() => {
</script> </script>
<style scoped> <style scoped>
.app-exit-btn {
position: fixed;
top: 0;
right: 0;
z-index: 3000;
width: 2.875rem;
height: 2rem;
display: flex;
align-items: center;
justify-content: center;
background: none;
border: none;
color: #fff;
font-size: 1rem;
line-height: 1;
cursor: pointer;
opacity: 0.7;
transition: opacity 0.15s;
}
.app-exit-btn:hover {
opacity: 1;
}
.player-indicator { .player-indicator {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
+5
View File
@@ -106,6 +106,11 @@ html.mouse-active ::-webkit-scrollbar-thumb:hover {
transition: top 0.6s cubic-bezier(0.4, 0, 0.2, 1); transition: top 0.6s cubic-bezier(0.4, 0, 0.2, 1);
} }
/* Leave room for the fixed app-exit button in desktop (pywebview) mode. */
.header--gui {
padding-right: 3.5rem;
}
.header::before { .header::before {
content: ""; content: "";
position: absolute; position: absolute;
+10
View File
@@ -1022,6 +1022,16 @@ class JsApi:
result = self._window.create_file_dialog(webview.FOLDER_DIALOG) result = self._window.create_file_dialog(webview.FOLDER_DIALOG)
return result[0] if result else None return result[0] if result else None
def exit_app(self) -> None:
"""Close the window, shutting the app down (like the OS close button)."""
if self._window:
self._window.destroy()
def toggle_fullscreen(self) -> None:
"""Switch between fullscreen and windowed mode in place."""
if self._window:
self._window.toggle_fullscreen()
def set_volume(self, x: float) -> None: def set_volume(self, x: float) -> None:
"""Set system master volume from slider position ``x`` (0.0 .. 1.5).""" """Set system master volume from slider position ``x`` (0.0 .. 1.5)."""
# Clamp to the platform's maximum so the slider never exceeds what # Clamp to the platform's maximum so the slider never exceeds what