mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-27 03:41:11 +01:00
Allow disabling window decorations/controls (#176)
Co-authored-by: Gregory Schier <gschier1990@gmail.com>
This commit is contained in:
committed by
GitHub
parent
432b366105
commit
be82b67ed3
@@ -1,9 +1,8 @@
|
||||
import { settingsAtom } from '@yaakapp-internal/models';
|
||||
import classNames from 'classnames';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import type { HTMLAttributes, ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
import { useOsInfo } from '../hooks/useOsInfo';
|
||||
import type { CSSProperties, HTMLAttributes, ReactNode } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useStoplightsVisible } from '../hooks/useStoplightsVisible';
|
||||
import { HEADER_SIZE_LG, HEADER_SIZE_MD, WINDOW_CONTROLS_WIDTH } from '../lib/constants';
|
||||
import { WindowControls } from './WindowControls';
|
||||
@@ -23,27 +22,42 @@ export function HeaderSize({
|
||||
onlyXWindowControl,
|
||||
children,
|
||||
}: HeaderSizeProps) {
|
||||
const osInfo = useOsInfo();
|
||||
const settings = useAtomValue(settingsAtom);
|
||||
const stoplightsVisible = useStoplightsVisible();
|
||||
const finalStyle = useMemo<CSSProperties>(() => {
|
||||
const s = { ...style };
|
||||
|
||||
// Set the height (use min-height because scaling font size may make it larger
|
||||
if (size === 'md') s.minHeight = HEADER_SIZE_MD;
|
||||
if (size === 'lg') s.minHeight = HEADER_SIZE_LG;
|
||||
|
||||
// Add large padding for window controls
|
||||
if (stoplightsVisible && !ignoreControlsSpacing) {
|
||||
s.paddingLeft = 72 / settings.interfaceScale;
|
||||
} else if (!stoplightsVisible && !ignoreControlsSpacing && !settings.hideWindowControls) {
|
||||
s.paddingRight = WINDOW_CONTROLS_WIDTH;
|
||||
}
|
||||
|
||||
return s;
|
||||
}, [
|
||||
ignoreControlsSpacing,
|
||||
settings.hideWindowControls,
|
||||
settings.interfaceScale,
|
||||
size,
|
||||
stoplightsVisible,
|
||||
style,
|
||||
]);
|
||||
|
||||
return (
|
||||
<div
|
||||
data-tauri-drag-region
|
||||
style={{
|
||||
...style,
|
||||
// Add padding for macOS stoplights, but keep it the same width (account for the interface scale)
|
||||
paddingLeft:
|
||||
stoplightsVisible && !ignoreControlsSpacing ? 72 / settings.interfaceScale : undefined,
|
||||
...(size === 'md' ? { minHeight: HEADER_SIZE_MD } : {}),
|
||||
...(size === 'lg' ? { minHeight: HEADER_SIZE_LG } : {}),
|
||||
...(osInfo.osType === 'macos' || ignoreControlsSpacing
|
||||
? { paddingRight: '2px' }
|
||||
: { paddingLeft: '2px', paddingRight: WINDOW_CONTROLS_WIDTH }),
|
||||
}}
|
||||
style={finalStyle}
|
||||
className={classNames(
|
||||
className,
|
||||
'px-1', // Give it some space on either end
|
||||
'pt-[1px]', // Make up for bottom border
|
||||
'select-none relative',
|
||||
'pt-[1px] w-full border-b border-border-subtle min-w-0',
|
||||
'w-full border-b border-border-subtle min-w-0',
|
||||
)}
|
||||
>
|
||||
{/* NOTE: This needs display:grid or else the element shrinks (even though scrollable) */}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useSearch } from '@tanstack/react-router';
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||
import { type } from '@tauri-apps/plugin-os';
|
||||
import classNames from 'classnames';
|
||||
import React, { useState } from 'react';
|
||||
import { useKeyPressEvent } from 'react-use';
|
||||
import { useOsInfo } from '../../hooks/useOsInfo';
|
||||
import { capitalize } from '../../lib/capitalize';
|
||||
import { HStack } from '../core/Stacks';
|
||||
import { TabContent, Tabs } from '../core/Tabs/Tabs';
|
||||
@@ -27,7 +27,6 @@ const tabs = [TAB_GENERAL, TAB_APPEARANCE, TAB_PROXY, TAB_PLUGINS, TAB_LICENSE]
|
||||
export type SettingsTab = (typeof tabs)[number];
|
||||
|
||||
export default function Settings({ hide }: Props) {
|
||||
const osInfo = useOsInfo();
|
||||
const { tab: tabFromQuery } = useSearch({ from: '/workspaces/$workspaceId/settings' });
|
||||
const [tab, setTab] = useState<string | undefined>(tabFromQuery);
|
||||
|
||||
@@ -60,9 +59,7 @@ export default function Settings({ hide }: Props) {
|
||||
justifyContent="center"
|
||||
className="w-full h-full grid grid-cols-[1fr_auto] pointer-events-none"
|
||||
>
|
||||
<div className={classNames(osInfo?.osType === 'macos' ? 'text-center' : 'pl-2')}>
|
||||
Settings
|
||||
</div>
|
||||
<div className={classNames(type() === 'macos' ? 'text-center' : 'pl-2')}>Settings</div>
|
||||
</HStack>
|
||||
</HeaderSize>
|
||||
)}
|
||||
|
||||
@@ -18,6 +18,7 @@ import type { SelectProps } from '../core/Select';
|
||||
import { Select } from '../core/Select';
|
||||
import { Separator } from '../core/Separator';
|
||||
import { HStack, VStack } from '../core/Stacks';
|
||||
import { type } from '@tauri-apps/plugin-os';
|
||||
|
||||
const fontSizeOptions = [
|
||||
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||
@@ -122,6 +123,15 @@ export function SettingsAppearance() {
|
||||
onChange={(editorSoftWrap) => patchModel(settings, { editorSoftWrap })}
|
||||
/>
|
||||
|
||||
{type() !== 'macos' && (
|
||||
<Checkbox
|
||||
checked={settings.hideWindowControls}
|
||||
title="Hide Window Controls"
|
||||
help="Hide the close/maximize/minimize controls on Windows or Linux"
|
||||
onChange={(hideWindowControls) => patchModel(settings, { hideWindowControls })}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Separator className="my-4" />
|
||||
|
||||
<Select
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||
import { type } from '@tauri-apps/plugin-os';
|
||||
import { settingsAtom } from '@yaakapp-internal/models';
|
||||
import classNames from 'classnames';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import React, { useState } from 'react';
|
||||
import { useOsInfo } from '../hooks/useOsInfo';
|
||||
import {WINDOW_CONTROLS_WIDTH} from "../lib/constants";
|
||||
import { WINDOW_CONTROLS_WIDTH } from '../lib/constants';
|
||||
import { Button } from './core/Button';
|
||||
import { HStack } from './core/Stacks';
|
||||
|
||||
@@ -14,10 +16,9 @@ interface Props {
|
||||
|
||||
export function WindowControls({ className, onlyX }: Props) {
|
||||
const [maximized, setMaximized] = useState<boolean>(false);
|
||||
const osInfo = useOsInfo();
|
||||
|
||||
// Never show controls on macOS
|
||||
if (osInfo.osType === 'macos') {
|
||||
const settings = useAtomValue(settingsAtom);
|
||||
// Never show controls on macOS or if hideWindowControls is true
|
||||
if (type() === 'macos' || settings.hideWindowControls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@ export function Checkbox({
|
||||
<HStack
|
||||
as="label"
|
||||
alignItems="center"
|
||||
space={3}
|
||||
space={2}
|
||||
className={classNames(className, 'text-text mr-auto')}
|
||||
>
|
||||
<div className={classNames(inputWrapperClassName, 'x-theme-input', 'relative flex')}>
|
||||
<div className={classNames(inputWrapperClassName, 'x-theme-input', 'relative flex mr-0.5')}>
|
||||
<input
|
||||
aria-hidden
|
||||
className={classNames(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import classNames from 'classnames';
|
||||
import type { HotkeyAction } from '../../hooks/useHotKey';
|
||||
import { useFormattedHotkey } from '../../hooks/useHotKey';
|
||||
import { useOsInfo } from '../../hooks/useOsInfo';
|
||||
import { HStack } from './Stacks';
|
||||
|
||||
interface Props {
|
||||
@@ -11,9 +10,8 @@ interface Props {
|
||||
}
|
||||
|
||||
export function HotKey({ action, className, variant }: Props) {
|
||||
const osInfo = useOsInfo();
|
||||
const labelParts = useFormattedHotkey(action);
|
||||
if (labelParts === null || osInfo == null) {
|
||||
if (labelParts === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import classNames from 'classnames';
|
||||
import type { CSSProperties, ReactNode } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useOsInfo } from '../../hooks/useOsInfo';
|
||||
import type { ButtonProps } from './Button';
|
||||
import { Button } from './Button';
|
||||
import { Label } from './Label';
|
||||
import type { RadioDropdownItem } from './RadioDropdown';
|
||||
import { RadioDropdown } from './RadioDropdown';
|
||||
import { HStack } from './Stacks';
|
||||
import { type } from '@tauri-apps/plugin-os';
|
||||
|
||||
export interface SelectProps<T extends string> {
|
||||
name: string;
|
||||
@@ -40,7 +40,6 @@ export function Select<T extends string>({
|
||||
defaultValue,
|
||||
size = 'md',
|
||||
}: SelectProps<T>) {
|
||||
const osInfo = useOsInfo();
|
||||
const [focused, setFocused] = useState<boolean>(false);
|
||||
const id = `input-${name}`;
|
||||
const isInvalidSelection = options.find((o) => 'value' in o && o.value === value) == null;
|
||||
@@ -63,7 +62,7 @@ export function Select<T extends string>({
|
||||
<Label htmlFor={id} visuallyHidden={hideLabel} className={labelClassName}>
|
||||
{label}
|
||||
</Label>
|
||||
{osInfo?.osType === 'macos' ? (
|
||||
{type() === 'macos' ? (
|
||||
<HStack
|
||||
space={2}
|
||||
className={classNames(
|
||||
|
||||
Reference in New Issue
Block a user