Introduce custom title bar

This commit is contained in:
onkofonko 2024-08-30 22:27:31 +02:00
parent 9cfdd02b91
commit 30578016b0
3 changed files with 181 additions and 35 deletions

View file

@ -1,42 +1,113 @@
<script>
import { persisted } from 'svelte-persisted-store'
import { getContext } from 'svelte'
import { click } from '@/modules/click.js'
import IPC from '@/modules/ipc.js'
import { persisted } from "svelte-persisted-store";
import { getContext } from "svelte";
import { click } from "@/modules/click.js";
import IPC from "@/modules/ipc.js";
export let page
const view = getContext('view')
function close () {
$view = null
page = 'home'
export let page;
const view = getContext("view");
function close() {
$view = null;
page = "home";
}
const debug = persisted('debug', '', {
const debug = persisted("debug", "", {
serializer: {
parse: e => e,
stringify: e => e
}
})
parse: (e) => e,
stringify: (e) => e,
},
});
function minimize() {
window.ipcRenderer.send("minimize");
}
function maximize() {
window.ipcRenderer.send("maximize");
}
function closeapp() {
window.ipcRenderer.send("closeapp");
}
</script>
<div class='w-full z-101 navbar bg-transparent border-0 p-0 d-flex'>
<div class='d-flex h-full draggable align-items-center text-center'>
{#if window.version?.platform !== 'darwin'}
<img src='./logo_filled.png' class='position-absolute w-50 h-50 m-10 pointer d-md-block d-none p-5' alt='ico' use:click={close} />
<div class="w-full z-101 navbar bg-transparent border-0 p-0 d-flex">
<div class="d-flex h-full draggable align-items-center text-center">
{#if window.version?.platform !== "darwin"}
<img
src="./logo_filled.png"
class="position-absolute w-50 h-50 m-10 pointer d-md-block d-none p-5"
alt="ico"
use:click={close}
/>
{/if}
</div>
<div class='h-full bg-dark flex-grow-1'>
{#if window.version?.platform === 'linux'}
<div class='d-flex align-items-center close h-full' use:click={() => IPC.emit('close')}>
<svg viewBox='0 0 24 24'>
<path d='M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z' />
<div id="window-controls">
<button class="button" id="max-button" on:click={minimize}>
<svg
class="svg-controls"
role="img"
width="12"
height="12"
viewBox="0 0 12 12"
><rect fill="currentColor" width="10" height="1" x="1" y="6"
></rect></svg
></button
>
<button class="button" id="restore-button" on:click={maximize}
><svg
class="svg-controls"
role="img"
width="12"
height="12"
viewBox="0 0 12 12"
><rect
width="9"
height="9"
x="1.5"
y="1.5"
fill="none"
stroke="currentColor"
></rect></svg
></button
>
<button class="button" id="close-button" on:click={closeapp}>
<svg
class="svg-controls"
role="img"
width="12"
height="12"
viewBox="0 0 12 12"
>
<polygon
fill="currentColor"
fill-rule="evenodd"
points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1"
></polygon></svg
></button
>
</div>
<div class="h-full bg-dark flex-grow-1">
{#if window.version?.platform === "linux"}
<div
class="d-flex align-items-center close h-full"
use:click={() => IPC.emit("close")}
>
<svg viewBox="0 0 24 24">
<path
d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"
/>
</svg>
</div>
{/if}
</div>
</div>
{#if $debug}
<div class='ribbon right z-101 text-center position-fixed font-size-16 font-weight-bold'>Debug Mode!</div>
<div
class="ribbon right z-101 text-center position-fixed font-size-16 font-weight-bold"
>
Debug Mode!
</div>
{/if}
<style>
@ -51,10 +122,10 @@
transform: translate(-29.3%) rotate(-45deg);
}
.navbar {
--navbar-height: 28px !important;
--navbar-height: 32px !important;
}
.z-101 {
z-index: 101 !important
z-index: 101 !important;
}
.draggable {
-webkit-app-region: drag;
@ -64,7 +135,7 @@
}
img {
top: 0;
-webkit-app-region: no-drag
-webkit-app-region: no-drag;
}
.close {
width: 40px;
@ -81,7 +152,7 @@
fill: currentColor;
}
.navbar {
left: unset !important
left: unset !important;
}
@media (pointer: none), (pointer: coarse) {
.navbar {
@ -89,4 +160,52 @@
height: 0;
}
}
#window-controls {
display: grid;
grid-template-columns: repeat(3, 46px);
position: absolute;
top: 0;
right: 0;
height: 100%;
}
#window-controls {
-webkit-app-region: no-drag;
}
#window-controls .button {
grid-row: 1 / span 1;
display: flex;
justify-content: center;
align-items: center;
width: 46px;
height: 32px;
background: transparent;
border: none;
color: #ffffff;
}
#window-controls .button {
user-select: none;
}
#window-controls .button:hover {
background: rgba(24, 24, 28, 0.2);
}
#window-controls .button:active {
background: rgba(24, 24, 28, 0.4);
}
#close-button:hover {
background: #e81123 !important;
}
#close-button:active {
background: #f1707a !important;
}
.svg-controls {
width: 12px;
height: 12px;
}
</style>

View file

@ -29,11 +29,6 @@ export default class App {
height: 900,
frame: process.platform === 'darwin', // Only keep the native frame on Mac
titleBarStyle: 'hidden',
titleBarOverlay: {
color: '#17191c',
symbolColor: '#eee',
height: 28
},
backgroundColor: '#17191c',
autoHideMenuBar: true,
webPreferences: {
@ -41,7 +36,9 @@ export default class App {
allowRunningInsecureContent: false,
enableBlinkFeatures: 'FontAccess, AudioVideoTracks',
backgroundThrottling: false,
preload: join(__dirname, '/preload.js')
preload: join(__dirname, '/preload.js'),
contextIsolation: true,
nodeIntegration: false
},
icon: join(__dirname, '/logo_filled.png'),
show: false
@ -159,3 +156,28 @@ export default class App {
if (!this.updater.install(forceRunAfter)) app.quit()
}
}
ipcMain.on('minimize', (event) => {
const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow) {
focusedWindow.minimize();
}
});
ipcMain.on('maximize', (event) => {
const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow) {
if (focusedWindow.isMaximized()) {
focusedWindow.unmaximize();
} else {
focusedWindow.maximize();
}
}
});
ipcMain.on('closeapp', (event) => {
const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow) {
focusedWindow.close();
}
});

View file

@ -29,4 +29,9 @@ ipcRenderer.once('port', ({ ports }) => {
ports[0].postMessage(a, b)
}
})
})
})
contextBridge.exposeInMainWorld('ipcRenderer', {
send: (channel, data) => ipcRenderer.send(channel, data),
on: (channel, callback) => ipcRenderer.on(channel, (event, ...args) => callback(...args)),
});