Use native dark theme titlebar on Windows
This commit is contained in:
parent
b574ba531d
commit
23e3883ce0
43 changed files with 152 additions and 965 deletions
|
@ -3,17 +3,12 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import type { ExecuteMenuRoleType } from './TitleBarContainer';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import { TitleBarContainer } from './TitleBarContainer';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
import { useTheme } from '../hooks/useTheme';
|
||||
|
||||
export type PropsType = {
|
||||
closeAbout: () => unknown;
|
||||
environment: string;
|
||||
executeMenuRole: ExecuteMenuRoleType;
|
||||
hasCustomTitleBar: boolean;
|
||||
i18n: LocalizerType;
|
||||
version: string;
|
||||
};
|
||||
|
@ -21,46 +16,36 @@ export type PropsType = {
|
|||
export function About({
|
||||
closeAbout,
|
||||
environment,
|
||||
executeMenuRole,
|
||||
hasCustomTitleBar,
|
||||
i18n,
|
||||
version,
|
||||
}: PropsType): JSX.Element {
|
||||
useEscapeHandling(closeAbout);
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<TitleBarContainer
|
||||
hasCustomTitleBar={hasCustomTitleBar}
|
||||
theme={theme}
|
||||
executeMenuRole={executeMenuRole}
|
||||
>
|
||||
<div className="About">
|
||||
<div className="module-splash-screen">
|
||||
<div className="module-splash-screen__logo module-img--150" />
|
||||
<div className="About">
|
||||
<div className="module-splash-screen">
|
||||
<div className="module-splash-screen__logo module-img--150" />
|
||||
|
||||
<div className="version">{version}</div>
|
||||
<div className="environment">{environment}</div>
|
||||
<div>
|
||||
<a href="https://signal.org">signal.org</a>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<a
|
||||
className="acknowledgments"
|
||||
href="https://github.com/signalapp/Signal-Desktop/blob/main/ACKNOWLEDGMENTS.md"
|
||||
>
|
||||
{i18n('icu:softwareAcknowledgments')}
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a className="privacy" href="https://signal.org/legal">
|
||||
{i18n('icu:privacyPolicy')}
|
||||
</a>
|
||||
</div>
|
||||
<div className="version">{version}</div>
|
||||
<div className="environment">{environment}</div>
|
||||
<div>
|
||||
<a href="https://signal.org">signal.org</a>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<a
|
||||
className="acknowledgments"
|
||||
href="https://github.com/signalapp/Signal-Desktop/blob/main/ACKNOWLEDGMENTS.md"
|
||||
>
|
||||
{i18n('icu:softwareAcknowledgments')}
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a className="privacy" href="https://signal.org/legal">
|
||||
{i18n('icu:privacyPolicy')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</TitleBarContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ import React, { useEffect } from 'react';
|
|||
import { Globals } from '@react-spring/web';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { ExecuteMenuRoleType } from './TitleBarContainer';
|
||||
import type { MenuOptionsType, MenuActionType } from '../types/menu';
|
||||
import type { AnyToast } from '../types/Toast';
|
||||
import type { ViewStoryActionCreatorType } from '../state/ducks/stories';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
|
@ -15,7 +13,6 @@ import { ThemeType } from '../types/Util';
|
|||
import { AppViewType } from '../state/ducks/app';
|
||||
import { SmartInstallScreen } from '../state/smart/InstallScreen';
|
||||
import { StandaloneRegistration } from './StandaloneRegistration';
|
||||
import { TitleBarContainer } from './TitleBarContainer';
|
||||
import { ToastManager } from './ToastManager';
|
||||
import { usePageVisibility } from '../hooks/usePageVisibility';
|
||||
import { useReducedMotion } from '../hooks/useReducedMotion';
|
||||
|
@ -42,18 +39,12 @@ type PropsType = {
|
|||
theme: ThemeType;
|
||||
isMaximized: boolean;
|
||||
isFullScreen: boolean;
|
||||
menuOptions: MenuOptionsType;
|
||||
onUndoArchive: (conversationId: string) => unknown;
|
||||
openFileInFolder: (target: string) => unknown;
|
||||
hasCustomTitleBar: boolean;
|
||||
OS: string;
|
||||
osClassName: string;
|
||||
hideMenuBar: boolean;
|
||||
|
||||
executeMenuRole: ExecuteMenuRoleType;
|
||||
executeMenuAction: (action: MenuActionType) => void;
|
||||
hideToast: () => unknown;
|
||||
titleBarDoubleClick: () => void;
|
||||
toast?: AnyToast;
|
||||
scrollToMessage: (conversationId: string, messageId: string) => unknown;
|
||||
viewStory: ViewStoryActionCreatorType;
|
||||
|
@ -62,16 +53,11 @@ type PropsType = {
|
|||
|
||||
export function App({
|
||||
appView,
|
||||
executeMenuAction,
|
||||
executeMenuRole,
|
||||
hasCustomTitleBar,
|
||||
hasSelectedStoryData,
|
||||
hideMenuBar,
|
||||
hideToast,
|
||||
i18n,
|
||||
isFullScreen,
|
||||
isMaximized,
|
||||
menuOptions,
|
||||
onUndoArchive,
|
||||
openFileInFolder,
|
||||
openInbox,
|
||||
|
@ -85,7 +71,6 @@ export function App({
|
|||
renderStoryViewer,
|
||||
requestVerification,
|
||||
theme,
|
||||
titleBarDoubleClick,
|
||||
toast,
|
||||
viewStory,
|
||||
}: PropsType): JSX.Element {
|
||||
|
@ -127,10 +112,6 @@ export function App({
|
|||
document.body.classList.add(osClassName);
|
||||
}, [osClassName]);
|
||||
|
||||
useEffect(() => {
|
||||
document.body.classList.toggle('os-has-custom-titlebar', hasCustomTitleBar);
|
||||
}, [hasCustomTitleBar]);
|
||||
|
||||
useEffect(() => {
|
||||
document.body.classList.toggle('full-screen', isFullScreen);
|
||||
document.body.classList.toggle('maximized', isMaximized);
|
||||
|
@ -150,41 +131,27 @@ export function App({
|
|||
}, [prefersReducedMotion]);
|
||||
|
||||
return (
|
||||
<TitleBarContainer
|
||||
theme={theme}
|
||||
isMaximized={isMaximized}
|
||||
isFullScreen={isFullScreen}
|
||||
hasCustomTitleBar={hasCustomTitleBar}
|
||||
executeMenuRole={executeMenuRole}
|
||||
titleBarDoubleClick={titleBarDoubleClick}
|
||||
hasMenu
|
||||
hideMenuBar={hideMenuBar}
|
||||
i18n={i18n}
|
||||
menuOptions={menuOptions}
|
||||
executeMenuAction={executeMenuAction}
|
||||
<div
|
||||
className={classNames({
|
||||
App: true,
|
||||
'light-theme': theme === ThemeType.light,
|
||||
'dark-theme': theme === ThemeType.dark,
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={classNames({
|
||||
App: true,
|
||||
'light-theme': theme === ThemeType.light,
|
||||
'dark-theme': theme === ThemeType.dark,
|
||||
})}
|
||||
>
|
||||
{contents}
|
||||
<ToastManager
|
||||
OS={OS}
|
||||
hideToast={hideToast}
|
||||
i18n={i18n}
|
||||
onUndoArchive={onUndoArchive}
|
||||
openFileInFolder={openFileInFolder}
|
||||
toast={toast}
|
||||
/>
|
||||
{renderGlobalModalContainer()}
|
||||
{renderCallManager()}
|
||||
{renderLightbox()}
|
||||
{hasSelectedStoryData &&
|
||||
renderStoryViewer(() => viewStory({ closeViewer: true }))}
|
||||
</div>
|
||||
</TitleBarContainer>
|
||||
{contents}
|
||||
<ToastManager
|
||||
OS={OS}
|
||||
hideToast={hideToast}
|
||||
i18n={i18n}
|
||||
onUndoArchive={onUndoArchive}
|
||||
openFileInFolder={openFileInFolder}
|
||||
toast={toast}
|
||||
/>
|
||||
{renderGlobalModalContainer()}
|
||||
{renderCallManager()}
|
||||
{renderLightbox()}
|
||||
{hasSelectedStoryData &&
|
||||
renderStoryViewer(() => viewStory({ closeViewer: true }))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -294,7 +294,7 @@ export function CallingPip({
|
|||
positionState.mode === PositionMode.BeingDragged
|
||||
? '-webkit-grabbing'
|
||||
: '-webkit-grab',
|
||||
transform: `translate3d(${localizedTranslateX}px,calc(${translateY}px - var(--titlebar-height)), 0)`,
|
||||
transform: `translate3d(${localizedTranslateX}px,calc(${translateY}px), 0)`,
|
||||
transition:
|
||||
positionState.mode === PositionMode.BeingDragged
|
||||
? 'none'
|
||||
|
|
|
@ -26,8 +26,6 @@ const createProps = (): PropsType => ({
|
|||
await sleep(5000);
|
||||
return 'https://picsum.photos/1800/900';
|
||||
},
|
||||
executeMenuRole: action('executeMenuRole'),
|
||||
hasCustomTitleBar: true,
|
||||
});
|
||||
|
||||
export default {
|
||||
|
|
|
@ -4,20 +4,17 @@
|
|||
import type { MouseEvent } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import copyText from 'copy-text-to-clipboard';
|
||||
import type { ExecuteMenuRoleType } from './TitleBarContainer';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as log from '../logging/log';
|
||||
import { Button, ButtonVariant } from './Button';
|
||||
import { Spinner } from './Spinner';
|
||||
import { TitleBarContainer } from './TitleBarContainer';
|
||||
import { ToastDebugLogError } from './ToastDebugLogError';
|
||||
import { ToastLinkCopied } from './ToastLinkCopied';
|
||||
import { ToastLoadingFullLogs } from './ToastLoadingFullLogs';
|
||||
import { createSupportUrl } from '../util/createSupportUrl';
|
||||
import { openLinkInWebBrowser } from '../util/openLinkInWebBrowser';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
import { useTheme } from '../hooks/useTheme';
|
||||
|
||||
enum LoadState {
|
||||
NotStarted,
|
||||
|
@ -32,8 +29,6 @@ export type PropsType = {
|
|||
i18n: LocalizerType;
|
||||
fetchLogs: () => Promise<string>;
|
||||
uploadLogs: (logs: string) => Promise<string>;
|
||||
hasCustomTitleBar: boolean;
|
||||
executeMenuRole: ExecuteMenuRoleType;
|
||||
};
|
||||
|
||||
enum ToastType {
|
||||
|
@ -48,8 +43,6 @@ export function DebugLogWindow({
|
|||
i18n,
|
||||
fetchLogs,
|
||||
uploadLogs,
|
||||
hasCustomTitleBar,
|
||||
executeMenuRole,
|
||||
}: PropsType): JSX.Element {
|
||||
const [loadState, setLoadState] = useState<LoadState>(LoadState.NotStarted);
|
||||
const [logText, setLogText] = useState<string | undefined>();
|
||||
|
@ -59,8 +52,6 @@ export function DebugLogWindow({
|
|||
);
|
||||
const [toastType, setToastType] = useState<ToastType | undefined>();
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
useEscapeHandling(closeWindow);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -144,41 +135,35 @@ export function DebugLogWindow({
|
|||
});
|
||||
|
||||
return (
|
||||
<TitleBarContainer
|
||||
hasCustomTitleBar={hasCustomTitleBar}
|
||||
theme={theme}
|
||||
executeMenuRole={executeMenuRole}
|
||||
>
|
||||
<div className="DebugLogWindow">
|
||||
<div>
|
||||
<div className="DebugLogWindow__title">
|
||||
{i18n('icu:debugLogSuccess')}
|
||||
</div>
|
||||
<p className="DebugLogWindow__subtitle">
|
||||
{i18n('icu:debugLogSuccessNextSteps')}
|
||||
</p>
|
||||
<div className="DebugLogWindow">
|
||||
<div>
|
||||
<div className="DebugLogWindow__title">
|
||||
{i18n('icu:debugLogSuccess')}
|
||||
</div>
|
||||
<div className="DebugLogWindow__container">
|
||||
<input
|
||||
className="DebugLogWindow__link"
|
||||
readOnly
|
||||
type="text"
|
||||
dir="auto"
|
||||
value={publicLogURL}
|
||||
/>
|
||||
</div>
|
||||
<div className="DebugLogWindow__footer">
|
||||
<Button
|
||||
onClick={() => openLinkInWebBrowser(supportURL)}
|
||||
variant={ButtonVariant.Secondary}
|
||||
>
|
||||
{i18n('icu:reportIssue')}
|
||||
</Button>
|
||||
<Button onClick={copyLog}>{i18n('icu:debugLogCopy')}</Button>
|
||||
</div>
|
||||
{toastElement}
|
||||
<p className="DebugLogWindow__subtitle">
|
||||
{i18n('icu:debugLogSuccessNextSteps')}
|
||||
</p>
|
||||
</div>
|
||||
</TitleBarContainer>
|
||||
<div className="DebugLogWindow__container">
|
||||
<input
|
||||
className="DebugLogWindow__link"
|
||||
readOnly
|
||||
type="text"
|
||||
dir="auto"
|
||||
value={publicLogURL}
|
||||
/>
|
||||
</div>
|
||||
<div className="DebugLogWindow__footer">
|
||||
<Button
|
||||
onClick={() => openLinkInWebBrowser(supportURL)}
|
||||
variant={ButtonVariant.Secondary}
|
||||
>
|
||||
{i18n('icu:reportIssue')}
|
||||
</Button>
|
||||
<Button onClick={copyLog}>{i18n('icu:debugLogCopy')}</Button>
|
||||
</div>
|
||||
{toastElement}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -188,49 +173,43 @@ export function DebugLogWindow({
|
|||
loadState === LoadState.Started || loadState === LoadState.Submitting;
|
||||
|
||||
return (
|
||||
<TitleBarContainer
|
||||
hasCustomTitleBar={hasCustomTitleBar}
|
||||
theme={theme}
|
||||
executeMenuRole={executeMenuRole}
|
||||
>
|
||||
<div className="DebugLogWindow">
|
||||
<div>
|
||||
<div className="DebugLogWindow__title">
|
||||
{i18n('icu:submitDebugLog')}
|
||||
</div>
|
||||
<p className="DebugLogWindow__subtitle">
|
||||
{i18n('icu:debugLogExplanation')}
|
||||
</p>
|
||||
<div className="DebugLogWindow">
|
||||
<div>
|
||||
<div className="DebugLogWindow__title">
|
||||
{i18n('icu:submitDebugLog')}
|
||||
</div>
|
||||
{isLoading ? (
|
||||
<div className="DebugLogWindow__container">
|
||||
<Spinner svgSize="normal" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="DebugLogWindow__scroll_area">
|
||||
<pre className="DebugLogWindow__scroll_area__text">
|
||||
{textAreaValue}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
<div className="DebugLogWindow__footer">
|
||||
<Button
|
||||
disabled={!canSave}
|
||||
onClick={() => {
|
||||
if (logText) {
|
||||
downloadLog(logText);
|
||||
}
|
||||
}}
|
||||
variant={ButtonVariant.Secondary}
|
||||
>
|
||||
{i18n('icu:debugLogSave')}
|
||||
</Button>
|
||||
<Button disabled={!canSubmit} onClick={handleSubmit}>
|
||||
{i18n('icu:submit')}
|
||||
</Button>
|
||||
</div>
|
||||
{toastElement}
|
||||
<p className="DebugLogWindow__subtitle">
|
||||
{i18n('icu:debugLogExplanation')}
|
||||
</p>
|
||||
</div>
|
||||
</TitleBarContainer>
|
||||
{isLoading ? (
|
||||
<div className="DebugLogWindow__container">
|
||||
<Spinner svgSize="normal" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="DebugLogWindow__scroll_area">
|
||||
<pre className="DebugLogWindow__scroll_area__text">
|
||||
{textAreaValue}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
<div className="DebugLogWindow__footer">
|
||||
<Button
|
||||
disabled={!canSave}
|
||||
onClick={() => {
|
||||
if (logText) {
|
||||
downloadLog(logText);
|
||||
}
|
||||
}}
|
||||
variant={ButtonVariant.Secondary}
|
||||
>
|
||||
{i18n('icu:debugLogSave')}
|
||||
</Button>
|
||||
<Button disabled={!canSubmit} onClick={handleSubmit}>
|
||||
{i18n('icu:submit')}
|
||||
</Button>
|
||||
</div>
|
||||
{toastElement}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -127,12 +127,10 @@ export const ModalHost = React.memo(function ModalHostInner({
|
|||
}
|
||||
|
||||
// Exemptions:
|
||||
// - TitleBar should always receive clicks.
|
||||
// - Quill suggestions since they are placed in the document.body
|
||||
// - Calling module (and pip) are always above everything else
|
||||
const exemptParent = target.closest(
|
||||
'.TitleBarContainer__title, ' +
|
||||
'.module-composition-input__suggestions, ' +
|
||||
'.module-composition-input__suggestions, ' +
|
||||
'.module-composition-input__format-menu, ' +
|
||||
'.module-calling__modal-container'
|
||||
);
|
||||
|
|
|
@ -82,7 +82,6 @@ export default {
|
|||
hasCallNotifications: true,
|
||||
hasCallRingtoneNotification: false,
|
||||
hasCountMutedConversations: false,
|
||||
hasCustomTitleBar: true,
|
||||
hasHideMenuBar: false,
|
||||
hasIncomingCallNotifications: true,
|
||||
hasLinkPreviews: true,
|
||||
|
@ -131,7 +130,6 @@ export default {
|
|||
doDeleteAllData: action('doDeleteAllData'),
|
||||
doneRendering: action('doneRendering'),
|
||||
editCustomColor: action('editCustomColor'),
|
||||
executeMenuRole: action('executeMenuRole'),
|
||||
makeSyncRequest: action('makeSyncRequest'),
|
||||
onAudioNotificationsChange: action('onAudioNotificationsChange'),
|
||||
onAutoConvertEmojiChange: action('onAutoConvertEmojiChange'),
|
||||
|
|
|
@ -33,7 +33,6 @@ import type {
|
|||
SentMediaQualityType,
|
||||
ThemeType,
|
||||
} from '../types/Util';
|
||||
import type { ExecuteMenuRoleType } from './TitleBarContainer';
|
||||
|
||||
import { Button, ButtonVariant } from './Button';
|
||||
import { ChatColorPicker } from './ChatColorPicker';
|
||||
|
@ -48,7 +47,6 @@ import { PhoneNumberDiscoverability } from '../util/phoneNumberDiscoverability';
|
|||
import { PhoneNumberSharingMode } from '../util/phoneNumberSharingMode';
|
||||
import { Select } from './Select';
|
||||
import { Spinner } from './Spinner';
|
||||
import { TitleBarContainer } from './TitleBarContainer';
|
||||
import { getCustomColorStyle } from '../util/getCustomColorStyle';
|
||||
import {
|
||||
DEFAULT_DURATIONS_IN_SECONDS,
|
||||
|
@ -58,7 +56,6 @@ import {
|
|||
import { DurationInSeconds } from '../util/durations';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
import { useUniqueId } from '../hooks/useUniqueId';
|
||||
import { useTheme } from '../hooks/useTheme';
|
||||
import { focusableSelectors } from '../util/focusableSelectors';
|
||||
import { Modal } from './Modal';
|
||||
import { SearchInput } from './SearchInput';
|
||||
|
@ -116,7 +113,6 @@ export type PropsDataType = {
|
|||
resolvedLocale: string;
|
||||
|
||||
// Other props
|
||||
hasCustomTitleBar: boolean;
|
||||
initialSpellCheckSetting: boolean;
|
||||
|
||||
// Limited support features
|
||||
|
@ -141,7 +137,6 @@ type PropsFunctionType = {
|
|||
doDeleteAllData: () => unknown;
|
||||
doneRendering: () => unknown;
|
||||
editCustomColor: (colorId: string, color: CustomColorType) => unknown;
|
||||
executeMenuRole: ExecuteMenuRoleType;
|
||||
getConversationsWithCustomColor: (
|
||||
colorId: string
|
||||
) => Promise<Array<ConversationType>>;
|
||||
|
@ -256,7 +251,6 @@ export function Preferences({
|
|||
doDeleteAllData,
|
||||
doneRendering,
|
||||
editCustomColor,
|
||||
executeMenuRole,
|
||||
getConversationsWithCustomColor,
|
||||
hasAudioNotifications,
|
||||
hasAutoConvertEmoji,
|
||||
|
@ -291,7 +285,6 @@ export function Preferences({
|
|||
isSyncSupported,
|
||||
isSystemTraySupported,
|
||||
isMinimizeToAndStartInSystemTraySupported,
|
||||
hasCustomTitleBar,
|
||||
lastSyncTime,
|
||||
makeSyncRequest,
|
||||
notificationContent,
|
||||
|
@ -364,7 +357,6 @@ export function Preferences({
|
|||
string | null
|
||||
>(localeOverride);
|
||||
const [languageSearchInput, setLanguageSearchInput] = useState('');
|
||||
const theme = useTheme();
|
||||
|
||||
function closeLanguageDialog() {
|
||||
setLanguageDialog(null);
|
||||
|
@ -1502,11 +1494,7 @@ export function Preferences({
|
|||
}
|
||||
|
||||
return (
|
||||
<TitleBarContainer
|
||||
hasCustomTitleBar={hasCustomTitleBar}
|
||||
theme={theme}
|
||||
executeMenuRole={executeMenuRole}
|
||||
>
|
||||
<>
|
||||
<div className="module-title-bar-drag-area" />
|
||||
<div className="Preferences">
|
||||
<div className="Preferences__page-selector">
|
||||
|
@ -1584,7 +1572,7 @@ export function Preferences({
|
|||
{settings}
|
||||
</div>
|
||||
</div>
|
||||
</TitleBarContainer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,274 +0,0 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import TitleBar from '@indutny/frameless-titlebar';
|
||||
import type { MenuItem } from '@indutny/frameless-titlebar';
|
||||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { createTemplate } from '../../app/menu';
|
||||
import { ThemeType } from '../types/Util';
|
||||
import type { LocalizerType } from '../types/I18N';
|
||||
import type { MenuOptionsType, MenuActionType } from '../types/menu';
|
||||
import { useIsWindowActive } from '../hooks/useIsWindowActive';
|
||||
|
||||
export type MenuPropsType = Readonly<{
|
||||
hasMenu: true;
|
||||
i18n: LocalizerType;
|
||||
menuOptions: MenuOptionsType;
|
||||
executeMenuAction: (action: MenuActionType) => void;
|
||||
}>;
|
||||
|
||||
export type ExecuteMenuRoleType = (
|
||||
role: MenuItemConstructorOptions['role']
|
||||
) => void;
|
||||
|
||||
export type PropsType = Readonly<{
|
||||
theme: ThemeType;
|
||||
isMaximized?: boolean;
|
||||
isFullScreen?: boolean;
|
||||
hasCustomTitleBar: boolean;
|
||||
hideMenuBar?: boolean;
|
||||
executeMenuRole: ExecuteMenuRoleType;
|
||||
titleBarDoubleClick?: () => void;
|
||||
children: ReactNode;
|
||||
}> &
|
||||
(MenuPropsType | { hasMenu?: false });
|
||||
|
||||
const TITLEBAR_HEIGHT = 28;
|
||||
|
||||
// Windows only
|
||||
const ROLE_TO_ACCELERATOR = new Map<
|
||||
MenuItemConstructorOptions['role'],
|
||||
string
|
||||
>();
|
||||
ROLE_TO_ACCELERATOR.set('undo', 'CmdOrCtrl+Z');
|
||||
ROLE_TO_ACCELERATOR.set('redo', 'CmdOrCtrl+Y');
|
||||
ROLE_TO_ACCELERATOR.set('cut', 'CmdOrCtrl+X');
|
||||
ROLE_TO_ACCELERATOR.set('copy', 'CmdOrCtrl+C');
|
||||
ROLE_TO_ACCELERATOR.set('paste', 'CmdOrCtrl+V');
|
||||
ROLE_TO_ACCELERATOR.set('pasteAndMatchStyle', 'CmdOrCtrl+Shift+V');
|
||||
ROLE_TO_ACCELERATOR.set('selectAll', 'CmdOrCtrl+A');
|
||||
ROLE_TO_ACCELERATOR.set('resetZoom', 'CmdOrCtrl+0');
|
||||
ROLE_TO_ACCELERATOR.set('zoomIn', 'CmdOrCtrl+=');
|
||||
ROLE_TO_ACCELERATOR.set('zoomOut', 'CmdOrCtrl+-');
|
||||
ROLE_TO_ACCELERATOR.set('togglefullscreen', 'F11');
|
||||
ROLE_TO_ACCELERATOR.set('toggleDevTools', 'CmdOrCtrl+Shift+I');
|
||||
ROLE_TO_ACCELERATOR.set('minimize', 'CmdOrCtrl+M');
|
||||
|
||||
function convertMenu(
|
||||
menuList: ReadonlyArray<MenuItemConstructorOptions>,
|
||||
executeMenuRole: (role: MenuItemConstructorOptions['role']) => void,
|
||||
i18n: LocalizerType
|
||||
): Array<MenuItem> {
|
||||
return menuList.map(item => {
|
||||
const {
|
||||
type,
|
||||
label,
|
||||
accelerator: originalAccelerator,
|
||||
click: originalClick,
|
||||
submenu: originalSubmenu,
|
||||
role,
|
||||
} = item;
|
||||
let submenu: Array<MenuItem> | undefined;
|
||||
|
||||
if (Array.isArray(originalSubmenu)) {
|
||||
submenu = convertMenu(originalSubmenu, executeMenuRole, i18n);
|
||||
} else if (originalSubmenu) {
|
||||
throw new Error('Non-array submenu is not supported');
|
||||
}
|
||||
|
||||
let click: (() => unknown) | undefined;
|
||||
if (originalClick) {
|
||||
if (role) {
|
||||
throw new Error(`Menu item: ${label} has both click and role`);
|
||||
}
|
||||
|
||||
// We don't use arguments in app/menu.ts
|
||||
click = originalClick as () => unknown;
|
||||
} else if (role) {
|
||||
click = () => executeMenuRole(role);
|
||||
}
|
||||
|
||||
let accelerator: string | undefined;
|
||||
if (originalAccelerator) {
|
||||
accelerator = originalAccelerator.toString();
|
||||
} else if (role) {
|
||||
accelerator = ROLE_TO_ACCELERATOR.get(role);
|
||||
}
|
||||
|
||||
// Custom titlebar is visible only on Windows and this string is used only
|
||||
// in UI. Actual accelerator interception is handled by Electron through
|
||||
// `app/main.ts`.
|
||||
accelerator = accelerator?.replace(
|
||||
/CommandOrControl|CmdOrCtrl/g,
|
||||
i18n('icu:Keyboard--Key--ctrl')
|
||||
);
|
||||
accelerator = accelerator?.replace(
|
||||
/Shift/g,
|
||||
i18n('icu:Keyboard--Key--shift')
|
||||
);
|
||||
|
||||
return {
|
||||
type,
|
||||
label,
|
||||
accelerator,
|
||||
click,
|
||||
submenu,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function TitleBarContainer(props: PropsType): JSX.Element {
|
||||
const {
|
||||
theme,
|
||||
isMaximized,
|
||||
isFullScreen,
|
||||
hasCustomTitleBar,
|
||||
hideMenuBar,
|
||||
executeMenuRole,
|
||||
titleBarDoubleClick,
|
||||
children,
|
||||
hasMenu,
|
||||
} = props;
|
||||
|
||||
const isWindowActive = useIsWindowActive();
|
||||
|
||||
const titleBarTheme = useMemo(
|
||||
() => ({
|
||||
bar: {
|
||||
// See stylesheets/_global.scss
|
||||
height: TITLEBAR_HEIGHT,
|
||||
palette:
|
||||
theme === ThemeType.light ? ('light' as const) : ('dark' as const),
|
||||
...(theme === ThemeType.dark
|
||||
? {
|
||||
// $color-gray-05
|
||||
color: '#e9e9e9',
|
||||
// $color-gray-80
|
||||
background: '#2e2e2e',
|
||||
// $color-gray-95
|
||||
borderBottom: '1px solid #121212',
|
||||
//
|
||||
button: {
|
||||
active: {
|
||||
// $color-gray-05
|
||||
color: '#e9e9e9',
|
||||
// $color-gray-75
|
||||
background: '#3b3b3b',
|
||||
},
|
||||
hover: {
|
||||
// $color-gray-05
|
||||
color: '#e9e9e9',
|
||||
// $color-gray-75
|
||||
background: '#3b3b3b',
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
|
||||
// Hide overlay
|
||||
menu: {
|
||||
overlay: {
|
||||
opacity: 0,
|
||||
},
|
||||
autoHide: hideMenuBar,
|
||||
|
||||
...(theme === ThemeType.dark
|
||||
? {
|
||||
separator: {
|
||||
// $color-gray-95
|
||||
color: '#5e5e5e',
|
||||
},
|
||||
accelerator: {
|
||||
// $color-gray-25
|
||||
color: '#b9b9b9',
|
||||
},
|
||||
list: {
|
||||
// $color-gray-75
|
||||
background: '#3b3b3b',
|
||||
boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.12)',
|
||||
borderRadius: '0px 0px 6px 6px',
|
||||
},
|
||||
}
|
||||
: {
|
||||
list: {
|
||||
boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.12)',
|
||||
borderRadius: '0px 0px 6px 6px',
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
// Zoom support
|
||||
enableOverflow: false,
|
||||
scalingFunction(value: string) {
|
||||
return `calc(${value} * var(--zoom-factor))`;
|
||||
},
|
||||
}),
|
||||
[theme, hideMenuBar]
|
||||
);
|
||||
|
||||
if (!hasCustomTitleBar) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
let maybeMenu: Array<MenuItem> | undefined;
|
||||
if (hasMenu) {
|
||||
const { i18n, menuOptions, executeMenuAction } = props;
|
||||
|
||||
const menuTemplate = createTemplate(
|
||||
{
|
||||
...menuOptions,
|
||||
|
||||
// actions
|
||||
forceUpdate: () => executeMenuAction('forceUpdate'),
|
||||
openArtCreator: () => executeMenuAction('openArtCreator'),
|
||||
openContactUs: () => executeMenuAction('openContactUs'),
|
||||
openForums: () => executeMenuAction('openForums'),
|
||||
openJoinTheBeta: () => executeMenuAction('openJoinTheBeta'),
|
||||
openReleaseNotes: () => executeMenuAction('openReleaseNotes'),
|
||||
openSupportPage: () => executeMenuAction('openSupportPage'),
|
||||
setupAsNewDevice: () => executeMenuAction('setupAsNewDevice'),
|
||||
setupAsStandalone: () => executeMenuAction('setupAsStandalone'),
|
||||
showAbout: () => executeMenuAction('showAbout'),
|
||||
showDebugLog: () => executeMenuAction('showDebugLog'),
|
||||
showKeyboardShortcuts: () => executeMenuAction('showKeyboardShortcuts'),
|
||||
showSettings: () => executeMenuAction('showSettings'),
|
||||
showWindow: () => executeMenuAction('showWindow'),
|
||||
zoomIn: () => executeMenuAction('zoomIn'),
|
||||
zoomOut: () => executeMenuAction('zoomOut'),
|
||||
zoomReset: () => executeMenuAction('zoomReset'),
|
||||
},
|
||||
i18n
|
||||
);
|
||||
|
||||
maybeMenu = convertMenu(menuTemplate, executeMenuRole, i18n);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'TitleBarContainer',
|
||||
isWindowActive ? 'TitleBarContainer--active' : null,
|
||||
isFullScreen ? 'TitleBarContainer--fullscreen' : null
|
||||
)}
|
||||
>
|
||||
<div className="TitleBarContainer__padding" />
|
||||
<div className="TitleBarContainer__content">{children}</div>
|
||||
|
||||
<TitleBar
|
||||
className="TitleBarContainer__title"
|
||||
platform="win32"
|
||||
iconSrc="images/titlebar_icon.svg"
|
||||
theme={titleBarTheme}
|
||||
maximized={isMaximized}
|
||||
menu={maybeMenu}
|
||||
onDoubleClick={titleBarDoubleClick}
|
||||
hideControls
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
|
||||
import type { MenuActionType } from '../../types/menu';
|
||||
import type { VerificationTransport } from '../../types/VerificationTransport';
|
||||
import { App } from '../../components/App';
|
||||
import OS from '../../util/os/osMain';
|
||||
|
@ -44,7 +42,6 @@ const mapStateToProps = (state: StateType) => {
|
|||
isMaximized: getIsMainWindowMaximized(state),
|
||||
isFullScreen: getIsMainWindowFullScreen(state),
|
||||
menuOptions: getMenuOptions(state),
|
||||
hasCustomTitleBar: window.SignalContext.OS.hasCustomTitleBar(),
|
||||
OS: OS.getName(),
|
||||
osClassName: OS.getClassName(),
|
||||
hideMenuBar: getHideMenuBar(state),
|
||||
|
@ -83,15 +80,6 @@ const mapStateToProps = (state: StateType) => {
|
|||
},
|
||||
theme: getTheme(state),
|
||||
|
||||
executeMenuRole: (role: MenuItemConstructorOptions['role']): void => {
|
||||
void window.SignalContext.executeMenuRole(role);
|
||||
},
|
||||
executeMenuAction: (action: MenuActionType): void => {
|
||||
void window.SignalContext.executeMenuAction(action);
|
||||
},
|
||||
titleBarDoubleClick: (): void => {
|
||||
window.IPC.titleBarDoubleClick();
|
||||
},
|
||||
toast: state.toast.toast,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -97,160 +97,6 @@
|
|||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2023-10-03T18:55:06.301Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-createRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " .map(() => createRef());",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const ref = useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const ref = useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const activeMenus = useRef((_a = menu === null || menu === void 0 ? void 0 : menu.length) !== null && _a !== void 0 ? _a : 0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const savedCallback = useRef(onClickAway);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const menuRef = useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const scrollRef = useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " myRef = myRef !== null && myRef !== void 0 ? myRef : useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const overflowRef = useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const menuBar = useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.es.js",
|
||||
"line": " const ref = useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-createRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " .map(() => React.createRef());",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const ref = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const ref = React.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const activeMenus = React.useRef((_a = menu === null || menu === void 0 ? void 0 : menu.length) !== null && _a !== void 0 ? _a : 0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const savedCallback = React.useRef(onClickAway);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const menuRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const scrollRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " myRef = myRef !== null && myRef !== void 0 ? myRef : React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const overflowRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const menuBar = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@indutny/frameless-titlebar/dist/index.js",
|
||||
"line": " const ref = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-06-06T22:58:37.359Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@ndelangen/get-tarball/dist/index.js",
|
||||
|
|
|
@ -22,7 +22,6 @@ function createIsPlatform(
|
|||
export type OSType = {
|
||||
getClassName: () => string;
|
||||
getName: () => string;
|
||||
hasCustomTitleBar: () => boolean;
|
||||
isLinux: (minVersion?: string) => boolean;
|
||||
isMacOS: (minVersion?: string) => boolean;
|
||||
isWindows: (minVersion?: string) => boolean;
|
||||
|
@ -33,10 +32,6 @@ export function getOSFunctions(osRelease: string): OSType {
|
|||
const isLinux = createIsPlatform('linux', osRelease);
|
||||
const isWindows = createIsPlatform('win32', osRelease);
|
||||
|
||||
// Windows 10 and above
|
||||
const hasCustomTitleBar = (): boolean =>
|
||||
isWindows('10.0.0') || Boolean(process.env.CUSTOM_TITLEBAR);
|
||||
|
||||
const getName = (): string => {
|
||||
if (isMacOS()) {
|
||||
return 'macOS';
|
||||
|
@ -60,7 +55,6 @@ export function getOSFunctions(osRelease: string): OSType {
|
|||
return {
|
||||
getClassName,
|
||||
getName,
|
||||
hasCustomTitleBar,
|
||||
isLinux,
|
||||
isMacOS,
|
||||
isWindows,
|
||||
|
|
|
@ -27,8 +27,6 @@ ReactDOM.render(
|
|||
<About
|
||||
closeAbout={() => window.SignalContext.executeMenuRole('close')}
|
||||
environment={environmentText}
|
||||
executeMenuRole={window.SignalContext.executeMenuRole}
|
||||
hasCustomTitleBar={window.SignalContext.OS.hasCustomTitleBar()}
|
||||
i18n={i18n}
|
||||
version={window.SignalContext.getVersion()}
|
||||
/>,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { ipcRenderer } from 'electron';
|
|||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
import { usernames } from '@signalapp/libsignal-client';
|
||||
|
||||
import type { MenuOptionsType, MenuActionType } from '../types/menu';
|
||||
import type { MenuOptionsType } from '../types/menu';
|
||||
import type { IPCEventsValuesType } from '../util/createIPCEvents';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import type { LoggerType } from '../types/Logging';
|
||||
|
@ -37,7 +37,6 @@ export type MainWindowStatsType = Readonly<{
|
|||
export type MinimalSignalContextType = {
|
||||
activeWindowService: ActiveWindowServiceType;
|
||||
config: RendererConfigType;
|
||||
executeMenuAction: (action: MenuActionType) => Promise<void>;
|
||||
executeMenuRole: (role: MenuItemConstructorOptions['role']) => Promise<void>;
|
||||
getAppInstance: () => string | undefined;
|
||||
getEnvironment: () => string;
|
||||
|
@ -62,7 +61,6 @@ export type MinimalSignalContextType = {
|
|||
waitForChange: () => Promise<void>;
|
||||
};
|
||||
OS: {
|
||||
hasCustomTitleBar: () => boolean;
|
||||
getClassName: () => string;
|
||||
platform: string;
|
||||
release: string;
|
||||
|
|
|
@ -13,8 +13,6 @@ strictAssert(DebugLogWindowProps, 'window values not provided');
|
|||
|
||||
render(
|
||||
<DebugLogWindow
|
||||
hasCustomTitleBar={window.SignalContext.OS.hasCustomTitleBar()}
|
||||
executeMenuRole={window.SignalContext.executeMenuRole}
|
||||
closeWindow={() => window.SignalContext.executeMenuRole('close')}
|
||||
downloadLog={DebugLogWindowProps.downloadLog}
|
||||
i18n={i18n}
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
document.body.classList.add(window.SignalContext.OS.getClassName());
|
||||
if (window.SignalContext.OS.hasCustomTitleBar()) {
|
||||
document.body.classList.add('os-has-custom-titlebar');
|
||||
}
|
||||
|
||||
if (window.SignalContext.renderWindow) {
|
||||
window.SignalContext.renderWindow();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
import { ipcRenderer } from 'electron';
|
||||
|
||||
import type { MenuOptionsType, MenuActionType } from '../types/menu';
|
||||
import type { MenuOptionsType } from '../types/menu';
|
||||
import type { MainWindowStatsType, MinimalSignalContextType } from './context';
|
||||
import { activeWindowService } from '../context/activeWindowService';
|
||||
import { config } from '../context/config';
|
||||
|
@ -14,13 +14,9 @@ import { environment } from '../context/environment';
|
|||
import { localeDisplayNames, localeMessages } from '../context/localeMessages';
|
||||
import { waitForSettingsChange } from '../context/waitForSettingsChange';
|
||||
|
||||
const hasCustomTitleBar = ipcRenderer.sendSync('OS.getHasCustomTitleBar');
|
||||
export const MinimalSignalContext: MinimalSignalContextType = {
|
||||
activeWindowService,
|
||||
config,
|
||||
async executeMenuAction(action: MenuActionType): Promise<void> {
|
||||
return ipcRenderer.invoke('executeMenuAction', action);
|
||||
},
|
||||
async executeMenuRole(
|
||||
role: MenuItemConstructorOptions['role']
|
||||
): Promise<void> {
|
||||
|
@ -55,7 +51,6 @@ export const MinimalSignalContext: MinimalSignalContextType = {
|
|||
restartApp: () => ipcRenderer.send('restart'),
|
||||
OS: {
|
||||
getClassName: () => ipcRenderer.sendSync('OS.getClassName'),
|
||||
hasCustomTitleBar: () => hasCustomTitleBar,
|
||||
platform: process.platform,
|
||||
release: config.osRelease,
|
||||
},
|
||||
|
|
|
@ -5,9 +5,6 @@ import './applyTheme';
|
|||
import { setupI18n } from '../util/setupI18n';
|
||||
|
||||
document.body.classList.add(window.SignalContext.OS.getClassName());
|
||||
if (window.SignalContext.OS.hasCustomTitleBar()) {
|
||||
document.body.classList.add('os-has-custom-titlebar');
|
||||
}
|
||||
|
||||
export const i18n = setupI18n(
|
||||
window.SignalContext.getI18nLocale(),
|
||||
|
|
|
@ -31,7 +31,6 @@ SettingsWindowProps.onRender(
|
|||
doDeleteAllData,
|
||||
doneRendering,
|
||||
editCustomColor,
|
||||
executeMenuRole,
|
||||
getConversationsWithCustomColor,
|
||||
hasAudioNotifications,
|
||||
hasAutoConvertEmoji,
|
||||
|
@ -40,7 +39,6 @@ SettingsWindowProps.onRender(
|
|||
hasCallNotifications,
|
||||
hasCallRingtoneNotification,
|
||||
hasCountMutedConversations,
|
||||
hasCustomTitleBar,
|
||||
hasHideMenuBar,
|
||||
hasIncomingCallNotifications,
|
||||
hasLinkPreviews,
|
||||
|
@ -134,7 +132,6 @@ SettingsWindowProps.onRender(
|
|||
doDeleteAllData={doDeleteAllData}
|
||||
doneRendering={doneRendering}
|
||||
editCustomColor={editCustomColor}
|
||||
executeMenuRole={executeMenuRole}
|
||||
getConversationsWithCustomColor={getConversationsWithCustomColor}
|
||||
hasAudioNotifications={hasAudioNotifications}
|
||||
hasAutoConvertEmoji={hasAutoConvertEmoji}
|
||||
|
@ -143,7 +140,6 @@ SettingsWindowProps.onRender(
|
|||
hasCallNotifications={hasCallNotifications}
|
||||
hasCallRingtoneNotification={hasCallRingtoneNotification}
|
||||
hasCountMutedConversations={hasCountMutedConversations}
|
||||
hasCustomTitleBar={hasCustomTitleBar}
|
||||
hasHideMenuBar={hasHideMenuBar}
|
||||
hasIncomingCallNotifications={hasIncomingCallNotifications}
|
||||
hasLinkPreviews={hasLinkPreviews}
|
||||
|
|
|
@ -426,9 +426,6 @@ async function renderPreferences() {
|
|||
onZoomFactorChange: (zoomFactorValue: number) => {
|
||||
ipcRenderer.send('setZoomFactor', zoomFactorValue);
|
||||
},
|
||||
|
||||
hasCustomTitleBar: MinimalSignalContext.OS.hasCustomTitleBar(),
|
||||
executeMenuRole: MinimalSignalContext.executeMenuRole,
|
||||
};
|
||||
|
||||
renderInBrowser(props);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue